# Mixpanel

> Send events to Mixpanel, keep user profiles current, export raw event data, and annotate the charts.

App · Analytics · 20 actions. Web page: https://docs.lodol.com/docs/integrations/mixpanel

## Actions

### Append to profile list

Add values to list properties on a person's Mixpanel profile, keeping duplicates. Use Merge into profile list instead when the list is a set and a repeat should be ignored.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Values to append (`properties`, object, required): Property names and the value to append to each.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$append",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Create annotation

Mark a moment on the project's charts with a note - a release, a campaign, an outage - so anyone reading a report later can see what caused the change.

**Inputs**

- When (`annotation_date`, date and time, required): The moment on the chart this note marks.
- Note (`description`, text, required): The text shown when someone hovers the marker.
- Tags (`tag_ids`, list): Tags to file this annotation under. Pick from the project's tags, or type an id - a tag created by an earlier step in this workflow is usable before the list has been refreshed.

**Outputs**

- `annotation` (object)
- `annotation_id` (number): The new annotation's id
- `status` (text): Status of the action execution ("success" on success).

**Example output**

```json
{
  "annotation": {
    "date": "2026-09-01 09:00:00",
    "description": "Pricing page redesign shipped to 100% of traffic",
    "id": 4821,
    "tags": [
      {
        "id": 12,
        "name": "Releases"
      }
    ],
    "user": {
      "first_name": "Alex",
      "id": 771,
      "last_name": "Rivera"
    }
  },
  "annotation_id": 4821,
  "status": "success"
}
```

### Create annotation tag

Create a tag that annotations can be filed under, such as Releases or Outages, so they can be filtered on a chart.

**Inputs**

- Tag name (`name`, text, required): The label shown on annotations carrying this tag.

**Outputs**

- `status` (text): Status of the action execution ("success" on success).
- `tag` (object)
- `tag_id` (number): The new tag's id

**Example output**

```json
{
  "status": "success",
  "tag": {
    "has_annotations": true,
    "id": 12,
    "name": "Releases",
    "project_id": 3018488
  },
  "tag_id": 12
}
```

### Delete annotation

Remove a Mixpanel annotation for good. Takes the annotation's numeric id.

**Inputs**

- Annotation (`annotation_id`, number, required): The annotation's numeric id. Use List annotations to find one.

**Outputs**

- `annotation_id` (number): The annotation that was deleted
- `deleted` (true/false): True once it is gone
- `status` (text): Status of the action execution ("success" on success).

**Example output**

```json
{
  "annotation_id": 4821,
  "deleted": true,
  "status": "success"
}
```

### Delete profile

Permanently delete a person's Mixpanel profile and all of its properties. Their events stay in the project - only Mixpanel's own privacy tools remove those.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Do not follow aliases (`ignore_alias`, true/false): Turn this on when deleting a duplicate profile. Without it Mixpanel follows the alias and deletes the original instead. Default: `false`.

**Outputs**

- `deleted` (true/false): True once it is gone
- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "deleted": true,
  "distinct_id": "user-4821",
  "operation": "$delete",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Delete profile properties

Permanently remove named properties, and their values, from a person's Mixpanel profile. The profile itself stays.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Properties to remove (`property_names`, list, required): Names of the properties to remove. Up to 255 in one call.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `properties_removed` (list): The property names that were removed
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$unset",
  "properties_removed": [
    "Trial Ends"
  ],
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Export raw events

Download events exactly as Mixpanel stored them, with every property, over a date range. Available on every Mixpanel plan.

**Inputs**

- From (`from_date`, date): First day to include. Leave both dates empty to read the last 7 days.
- To (`to_date`, date): Last day to include. Leave both dates empty to read the last 7 days.
- Only these events (`event_names`, list): Names of the events to include. Leave empty for all of them.
- Filter expression (`where`, text): A Mixpanel expression, such as properties["Plan"] == "premium". Leave empty for everything. The grammar is at https://docs.mixpanel.com/reference/segmentation-expressions
- How many events (`limit`, number): The most events to return. Defaults to 100. A workflow step holds the whole result in memory, so keep this modest. From 1 to 10000. Default: `100`.

**Outputs**

- `count` (number): How many events came back
- `events` (list)
- `from_date` (text): First day read
- `status` (text): Status of the action execution ("success" on success).
- `to_date` (text): Last day read

**Example output**

```json
{
  "count": 1,
  "events": [
    {
      "event": "Invoice Paid",
      "properties": {
        "$insert_id": "b3f1c2d4-5e6a-47b8-9c0d-1e2f3a4b5c6d",
        "Amount": 49,
        "distinct_id": "user-4821",
        "time": 1788000000
      }
    }
  ],
  "from_date": "2026-09-01",
  "status": "success",
  "to_date": "2026-09-07"
}
```

### Find profiles

Read user profiles out of Mixpanel, filtered by an expression or by a list of ids. Available on every Mixpanel plan.

**Inputs**

- Filter expression (`where`, text): A Mixpanel expression, such as properties["Plan"] == "premium". Leave empty for everything. The grammar is at https://docs.mixpanel.com/reference/segmentation-expressions
- Only these people (`distinct_ids`, list): Distinct IDs to look up. Leave empty to use the filter expression instead.
- Only these properties (`output_properties`, list): Property names to return. Naming the few you need makes the query markedly faster on a large project. Leave empty for all of them.
- Only this cohort (`filter_by_cohort_id`, number): The numeric id of a saved cohort to draw from. Saving cohorts needs a paid Mixpanel plan, so leave this empty on a free project.
- Include people with no profile (`include_all_users`, true/false): Only applies when a cohort is given. On by default, which includes everyone in the cohort even if they have no profile. Default: `true`.
- Page (`page`, number): Which page to read, counting from 0. Anything above 0 also needs the session id from the first page. From 0 to 10000.
- Session ID (`session_id`, text): The session id returned by the first page, which is what lets Mixpanel page through the same result instead of running the search again.

**Outputs**

- `count` (number): How many profiles are on this page
- `page` (number): The page number returned
- `page_size` (number): The most profiles Mixpanel puts on one page
- `profiles` (list)
- `session_id` (text): Pass this back to read the next page
- `status` (text): Status of the action execution ("success" on success).
- `total` (number): How many profiles match in total

**Example output**

```json
{
  "count": 1,
  "page": 0,
  "page_size": 1000,
  "profiles": [
    {
      "$distinct_id": "user-4821",
      "$properties": {
        "$email": "alex@example.com",
        "$name": "Alex Rivera",
        "Plan": "premium"
      }
    }
  ],
  "session_id": "1788000000-EXAMPL",
  "status": "success",
  "total": 1
}
```

### Get annotation

Read one Mixpanel annotation by its id, with its date, note, tags and who created it.

**Inputs**

- Annotation (`annotation_id`, number, required): The annotation's numeric id. Use List annotations to find one.

**Outputs**

- `annotation` (object)
- `annotation_id` (number): The annotation's id
- `status` (text): Status of the action execution ("success" on success).

**Example output**

```json
{
  "annotation": {
    "date": "2026-09-01 09:00:00",
    "description": "Pricing page redesign shipped to 100% of traffic",
    "id": 4821,
    "tags": [
      {
        "id": 12,
        "name": "Releases"
      }
    ],
    "user": {
      "first_name": "Alex",
      "id": 771,
      "last_name": "Rivera"
    }
  },
  "annotation_id": 4821,
  "status": "success"
}
```

### Import events

Load a batch of events into Mixpanel, including ones that already happened. Use this for backfills and for anything older than the last hour, which Send event will not take. Needs the service account to be an Owner or an Admin.

**Inputs**

- Events (`events`, list, required): The events to load. Each needs a name and one of distinct_id, user_id or device_id; a time and a deduplication id are filled in when you leave them out. Up to 2000 per call.

**Outputs**

- `events_imported` (number): How many Mixpanel reported it stored
- `events_submitted` (number): How many events this call sent
- `insert_ids` (list): The deduplication id of each event, generated where one was not supplied - resend these to retry safely.
- `status` (text): Status of the action execution ("success" on success).

**Example output**

```json
{
  "events_imported": 2,
  "events_submitted": 2,
  "insert_ids": [
    "b3f1c2d4-5e6a-47b8-9c0d-1e2f3a4b5c6d",
    "c4a2d3e5-6f7b-48c9-8d1e-2f3a4b5c6d7e"
  ],
  "status": "success"
}
```

### Increment profile properties

Add to numeric properties on a person's Mixpanel profile - a login count, a lifetime spend. A negative amount subtracts, and a property that does not exist yet counts up from zero.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Amounts to add (`properties`, object, required): Property names and the number to add to each.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$add",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### List annotation tags

List the tags this project's annotations can be filed under, with the numeric ids the other annotation actions want.

**Inputs**: None.

**Outputs**

- `count` (number): How many came back
- `status` (text): Status of the action execution ("success" on success).
- `tags` (list)

**Example output**

```json
{
  "count": 1,
  "status": "success",
  "tags": [
    {
      "has_annotations": true,
      "id": 12,
      "name": "Releases",
      "project_id": 3018488
    }
  ]
}
```

### List annotations

List the project's chart annotations, optionally only those inside a date range.

**Inputs**

- From (`from_date`, date): First day to include. Leave both dates empty for every annotation in the project.
- To (`to_date`, date): Last day to include. Leave both dates empty for every annotation in the project.

**Outputs**

- `annotations` (list)
- `count` (number): How many came back
- `status` (text): Status of the action execution ("success" on success).

**Example output**

```json
{
  "annotations": [
    {
      "date": "2026-09-01 09:00:00",
      "description": "Pricing page redesign shipped to 100% of traffic",
      "id": 4821,
      "tags": [
        {
          "id": 12,
          "name": "Releases"
        }
      ],
      "user": {
        "first_name": "Alex",
        "id": 771,
        "last_name": "Rivera"
      }
    }
  ],
  "count": 1,
  "status": "success"
}
```

### Merge into profile list

Add values to list properties on a person's Mixpanel profile, skipping any the list already holds. This is the one to use for tags, plans and features, where a value should appear once.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Values to merge in (`properties`, object, required): Property names and a list of values for each. Each value must be a list, even for a single entry.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$union",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Remove from profile list

Take values out of list properties on a person's Mixpanel profile.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Values to remove (`properties`, object, required): Property names and the value to remove from each.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$remove",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Send event

Record one event in Mixpanel for a person, with any properties you want attached. Use this to get whatever a workflow does into your product analytics as it happens.

**Inputs**

- Event name (`event`, text, required): What happened, as you want it to appear in Mixpanel - for example 'Invoice Paid'. A new name creates a new event.
- Distinct ID (`distinct_id`, text): Mixpanel's identifier for this person. Leave empty to let Mixpanel derive it from the User ID or Device ID. Give at least one of Distinct ID, User ID or Device ID. Mixpanel cannot attribute an event that has none of them.
- User ID (`user_id`, text): Your own id for this person once they are known - their id in your database. Mixpanel stores it as $user_id and makes it the canonical Distinct ID. Give at least one of Distinct ID, User ID or Device ID. Mixpanel cannot attribute an event that has none of them.
- Device ID (`device_id`, text): The anonymous id this person browsed under before they were known. Sending it alongside a User ID is what stitches their pre-login and post-login activity into one person. Give at least one of Distinct ID, User ID or Device ID. Mixpanel cannot attribute an event that has none of them.
- Event properties (`properties`, object): Details of this occurrence, as name/value pairs.
- When it happened (`time`, date and time): Leave empty for now. Mixpanel keeps events roughly in the present here - use Import events for anything older.
- Deduplication ID (`insert_id`, text): An id unique to this occurrence, so a workflow that runs twice records the event once. Letters, digits and hyphens, up to 36 characters.
- IP address (`ip`, text): The person's IP address, if you have it, so Mixpanel can fill in their city and country. Leave empty to record no location - the alternative would be this server's.

**Outputs**

- `distinct_id` (text): Who Mixpanel attributed the event to
- `event` (text): The event name recorded
- `insert_id` (text): The deduplication id sent, if any
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "event": "Invoice Paid",
  "insert_id": "b3f1c2d4-5e6a-47b8-9c0d-1e2f3a4b5c6d",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Set profile properties

Set properties on a person's Mixpanel profile, replacing whatever was there. Creates the profile if it does not exist. Mixpanel's own names start with a dollar sign - $email, $name, $phone.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Properties (`properties`, object, required): The properties to set, as name/value pairs.
- Update the profile's location from this request (`update_geolocation`, true/false): Off by default, and usually right to leave off: the request comes from a Lodol server, so turning this on stamps a data centre's city onto the profile instead of the person's. Default: `false`.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$set",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Set profile properties once

Set properties on a person's Mixpanel profile only where nothing is set yet, leaving existing values alone. Use it for things that should record the first time they happened, such as a signup date or first referrer.

**Inputs**

- Distinct ID (`distinct_id`, text, required): Whose profile to change. This is the person's canonical Distinct ID - the same value as their User ID on a project using Simplified ID Merge.
- Properties (`properties`, object, required): The properties to set if they are not set already.
- Update the profile's location from this request (`update_geolocation`, true/false): Off by default, and usually right to leave off: the request comes from a Lodol server, so turning this on stamps a data centre's city onto the profile instead of the person's. Default: `false`.

**Outputs**

- `distinct_id` (text): Whose profile was changed
- `operation` (text): The Mixpanel operation used, such as $set
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_id": "user-4821",
  "operation": "$set_once",
  "records_accepted": 1,
  "status": "success",
  "verbose": true
}
```

### Update annotation

Change a Mixpanel annotation's note or its tags. Its date cannot be moved through the API - delete it and create another to change when it marks.

**Inputs**

- Annotation (`annotation_id`, number, required): The annotation's numeric id. Use List annotations to find one.
- Note (`description`, text): New text for the annotation. Leave empty to keep it.
- Tags (`tag_ids`, list): Tags to file this annotation under. Pick from the project's tags, or type an id - a tag created by an earlier step in this workflow is usable before the list has been refreshed.

**Outputs**

- `annotation` (object)
- `annotation_id` (number): The annotation's id
- `status` (text): Status of the action execution ("success" on success).

**Example output**

```json
{
  "annotation": {
    "date": "2026-09-01 09:00:00",
    "description": "Pricing page redesign shipped to 100% of traffic",
    "id": 4821,
    "tags": [
      {
        "id": 12,
        "name": "Releases"
      }
    ],
    "user": {
      "first_name": "Alex",
      "id": 771,
      "last_name": "Rivera"
    }
  },
  "annotation_id": 4821,
  "status": "success"
}
```

### Update many profiles

Apply a list of profile changes in one call, each naming its own person and operation. Use this instead of a loop when a workflow has a list of people to update.

**Inputs**

- Updates (`updates`, list, required): One entry per change. Each needs a $distinct_id and exactly one operation: $set, $set_once, $add, $union, $append, $remove, $unset or $delete. Up to 2000 per call.

**Outputs**

- `distinct_ids` (list): The profiles that were changed
- `records_accepted` (number): How many records this call sent and Mixpanel accepted
- `status` (text): Status of the action execution ("success" on success).
- `verbose` (true/false): True when Mixpanel confirmed the write in detail. False means it answered the short form, which does not distinguish a good project token from a bad one.

**Example output**

```json
{
  "distinct_ids": [
    "user-4821",
    "user-4822"
  ],
  "records_accepted": 2,
  "status": "success",
  "verbose": true
}
```
