Skip to content

Data Governance

Manage Mixpanel data governance programmatically: Lexicon definitions (events, properties, tags), drop filters, custom properties, custom events, lookup tables, schema registry, schema enforcement, data auditing, volume anomalies, and event deletion requests. Full CRUD operations with bulk support.

Prerequisites

Data governance requires authentication — service account or OAuth credentials.

All data governance operations require a workspace ID — set via MP_WORKSPACE_ID env var, --workspace-id CLI flag, or ws.set_workspace_id(). Find yours with mp inspect info or ws.info().

Read-Only Discovery

For read-only Lexicon schema exploration (listing events/properties with descriptions and metadata), see the Discovery guide — Lexicon Schemas. This guide covers write operations: creating, updating, and deleting definitions.

Lexicon — Event Definitions

Get Event Definitions

import mixpanel_data as mp

ws = mp.Workspace()

# Get definitions for specific events
defs = ws.get_event_definitions(names=["Signup", "Login"])
for d in defs:
    print(f"{d.name}: {d.description}")
    print(f"  hidden={d.hidden}, verified={d.verified}")
    print(f"  tags={d.tags}")
# Get definitions by name
mp lexicon events get --names "Signup,Login"

# Table format for quick scanning
mp lexicon events get --names "Signup,Login" --format table

Update an Event Definition

definition = ws.update_event_definition(
    "Signup",
    mp.UpdateEventDefinitionParams(
        description="User signed up for an account",
        verified=True,
        tags=["core", "acquisition"],
    ),
)
print(f"Updated: {definition.name}")
mp lexicon events update --name "Signup" \
    --description "User signed up for an account" \
    --verified \
    --tags "core,acquisition"

Delete an Event Definition

ws.delete_event_definition("OldEvent")
mp lexicon events delete --name "OldEvent"

Bulk Update Event Definitions

Update multiple event definitions in a single API call:

results = ws.bulk_update_event_definitions(
    mp.BulkUpdateEventsParams(events=[
        mp.BulkEventUpdate(name="OldEvent", hidden=True),
        mp.BulkEventUpdate(name="NewEvent", verified=True),
        mp.BulkEventUpdate(
            name="Purchase",
            description="Completed purchase",
            tags=["revenue"],
        ),
    ])
)
for d in results:
    print(f"{d.name}: hidden={d.hidden}, verified={d.verified}")
mp lexicon events bulk-update --data '{
    "events": [
        {"name": "OldEvent", "hidden": true},
        {"name": "NewEvent", "verified": true},
        {"name": "Purchase", "description": "Completed purchase", "tags": ["revenue"]}
    ]
}'

Lexicon — Property Definitions

Get Property Definitions

# Get property definitions by name
defs = ws.get_property_definitions(
    names=["plan_type", "country"],
    resource_type="event",  # "event", "user", or "groupprofile"
)
for d in defs:
    print(f"{d.name} ({d.resource_type}): {d.description}")
    print(f"  sensitive={d.sensitive}, hidden={d.hidden}")
# Get property definitions
mp lexicon properties get --names "plan_type,country"

# Filter by resource type
mp lexicon properties get --names "plan_type" --resource-type event

Update a Property Definition

definition = ws.update_property_definition(
    "plan_type",
    mp.UpdatePropertyDefinitionParams(
        description="User subscription tier",
        sensitive=False,
    ),
)
mp lexicon properties update --name "plan_type" \
    --description "User subscription tier" \
    --no-sensitive

Bulk Update Property Definitions

results = ws.bulk_update_property_definitions(
    mp.BulkUpdatePropertiesParams(properties=[
        mp.BulkPropertyUpdate(
            name="email",
            resource_type="user",
            sensitive=True,
        ),
        mp.BulkPropertyUpdate(
            name="country",
            resource_type="event",
            description="User country code",
        ),
    ])
)
mp lexicon properties bulk-update --data '{
    "properties": [
        {"name": "email", "resource_type": "user", "sensitive": true},
        {"name": "country", "resource_type": "event", "description": "User country code"}
    ]
}'

Lexicon — Tags

Organize event and property definitions with tags.

List Tags

tags = ws.list_lexicon_tags()
for tag in tags:
    print(f"{tag.id}: {tag.name}")
mp lexicon tags list
mp lexicon tags list --format table

Create a Tag

tag = ws.create_lexicon_tag(mp.CreateTagParams(name="core-events"))
print(f"Created tag {tag.id}: {tag.name}")
mp lexicon tags create --name "core-events"

Update a Tag

tag = ws.update_lexicon_tag(5, mp.UpdateTagParams(name="renamed-tag"))
mp lexicon tags update --id 5 --name "renamed-tag"

Delete a Tag

ws.delete_lexicon_tag("deprecated-tag")
mp lexicon tags delete --name "deprecated-tag"

Lexicon — Tracking & History

Tracking Metadata

Get tracking metadata for an event (sources, SDKs, volume):

metadata = ws.get_tracking_metadata("Signup")
print(metadata)  # Raw tracking metadata dictionary
mp lexicon tracking-metadata --event-name "Signup"

Event History

View the change history for an event definition:

history = ws.get_event_history("Signup")
for entry in history:
    print(entry)  # Chronological list of changes
mp lexicon event-history --event-name "Signup"

Property History

View the change history for a property definition:

history = ws.get_property_history("plan_type", entity_type="event")
for entry in history:
    print(entry)
mp lexicon property-history --property-name "plan_type" --entity-type "event"

Export Lexicon

Export all Lexicon data definitions:

export = ws.export_lexicon()
print(export)  # Raw export dictionary

# Filter by type
export = ws.export_lexicon(
    export_types=["events", "event_properties"]
)
mp lexicon export
mp lexicon export --types "events,event_properties,user_properties"

Drop Filters

Drop filters suppress events at ingestion time, preventing them from being stored or counted.

List Drop Filters

import mixpanel_data as mp

ws = mp.Workspace()

filters = ws.list_drop_filters()
for f in filters:
    print(f"{f.id}: {f.event_name} (active={f.active})")
mp drop-filters list
mp drop-filters list --format table

Create a Drop Filter

filters = ws.create_drop_filter(
    mp.CreateDropFilterParams(
        event_name="Debug Event",
        filters={"property": "env", "value": "test"},
    )
)
# Returns full list of drop filters after creation
mp drop-filters create --event-name "Debug Event" \
    --filters '{"property": "env", "value": "test"}'

Update a Drop Filter

filters = ws.update_drop_filter(
    mp.UpdateDropFilterParams(
        id=42,
        event_name="Debug Event v2",
        active=False,
    )
)
mp drop-filters update --id 42 --event-name "Debug Event v2" --no-active

Delete a Drop Filter

remaining = ws.delete_drop_filter(42)
# Returns full list of remaining drop filters
mp drop-filters delete --id 42

Drop Filter Limits

limits = ws.get_drop_filter_limits()
print(f"Drop filter limit: {limits.filter_limit}")
mp drop-filters limits

Custom Properties

Custom properties are computed properties defined by formulas or behaviors. They calculate values dynamically from existing event or profile properties.

PUT Semantics

Custom property update uses full replacement (PUT semantics). The resource_type and data_group_id fields are immutable after creation.

List Custom Properties

import mixpanel_data as mp

ws = mp.Workspace()

props = ws.list_custom_properties()
for p in props:
    print(f"{p.name}: {p.display_formula}")
mp custom-properties list
mp custom-properties list --format table

Get a Custom Property

prop = ws.get_custom_property("abc123")
print(f"{prop.name}: {prop.display_formula}")
print(f"  resource_type={prop.resource_type}")
mp custom-properties get --id "abc123"

Create a Custom Property

Custom properties can be formula-based or behavior-based:

# Formula-based custom property
prop = ws.create_custom_property(
    mp.CreateCustomPropertyParams(
        name="Full Name",
        resource_type="events",
        display_formula='concat(properties["first"], " ", properties["last"])',
        composed_properties={
            "first": mp.ComposedPropertyValue(resource_type="event"),
            "last": mp.ComposedPropertyValue(resource_type="event"),
        },
    )
)
print(f"Created: {prop.name} (ID: {prop.custom_property_id})")
mp custom-properties create \
    --name "Full Name" \
    --resource-type events \
    --display-formula 'concat(properties["first"], " ", properties["last"])' \
    --composed-properties '{"first": {"resource_type": "event"}, "last": {"resource_type": "event"}}'

Formula vs Behavior

display_formula and behavior are mutually exclusive. If using display_formula, you must also provide composed_properties that map the referenced properties.

Update a Custom Property

prop = ws.update_custom_property(
    "abc123",
    mp.UpdateCustomPropertyParams(name="Renamed Property"),
)
mp custom-properties update --id "abc123" --name "Renamed Property"

Delete a Custom Property

ws.delete_custom_property("abc123")
mp custom-properties delete --id "abc123"

Validate a Custom Property

Check whether a custom property definition is valid before creating it:

result = ws.validate_custom_property(
    mp.CreateCustomPropertyParams(
        name="Revenue Per User",
        resource_type="events",
        display_formula='number(properties["amount"])',
        composed_properties={
            "amount": mp.ComposedPropertyValue(resource_type="event"),
        },
    )
)
print(result)  # Validation result dictionary
mp custom-properties validate \
    --name "Revenue Per User" \
    --resource-type events \
    --display-formula 'number(properties["amount"])' \
    --composed-properties '{"amount": {"resource_type": "event"}}'

Custom Events

Custom events are composite events built from combinations of existing events. They share the same EventDefinition type as regular events.

List Custom Events

import mixpanel_data as mp

ws = mp.Workspace()

events = ws.list_custom_events()
for e in events:
    print(f"{e.name}: {e.description}")
mp custom-events list
mp custom-events list --format table

Update a Custom Event

event = ws.update_custom_event(
    "My Custom Event",
    mp.UpdateEventDefinitionParams(
        description="Updated description",
        verified=True,
    ),
)
mp custom-events update --name "My Custom Event" \
    --description "Updated description" --verified

Delete a Custom Event

ws.delete_custom_event("My Custom Event")
mp custom-events delete --name "My Custom Event"

Lookup Tables

Lookup tables are CSV-based reference data used to enrich event and profile properties. Upload a CSV, and Mixpanel maps its columns to properties for real-time enrichment.

List Lookup Tables

import mixpanel_data as mp

ws = mp.Workspace()

tables = ws.list_lookup_tables()
for t in tables:
    print(f"{t.name} (ID: {t.id}, mapped={t.has_mapped_properties})")

# Filter by data group
tables = ws.list_lookup_tables(data_group_id=123)
mp lookup-tables list
mp lookup-tables list --data-group-id 123
mp lookup-tables list --format table

Upload a Lookup Table

3-Step Upload Process

upload_lookup_table() handles the full workflow automatically:

  1. Obtains a signed upload URL from the API
  2. Uploads the CSV file to the signed URL
  3. Registers the lookup table

For files >= 5 MB, processing is asynchronous. The method automatically polls for completion with configurable timeout.

table = ws.upload_lookup_table(
    mp.UploadLookupTableParams(
        name="Country Codes",
        file_path="/path/to/countries.csv",
    ),
    poll_interval=2.0,        # Seconds between polls (async only)
    max_poll_seconds=300.0,   # Max wait time (async only)
)
print(f"Created: {table.name} (ID: {table.id})")

# Replace an existing lookup table
table = ws.upload_lookup_table(
    mp.UploadLookupTableParams(
        name="Country Codes",
        file_path="/path/to/countries_v2.csv",
        data_group_id=456,  # Existing table's data group ID
    )
)
# Upload a new lookup table
mp lookup-tables upload --name "Country Codes" --file "/path/to/countries.csv"

# Replace an existing lookup table
mp lookup-tables upload --name "Country Codes" --file "/path/to/countries_v2.csv" \
    --data-group-id 456

Update a Lookup Table

table = ws.update_lookup_table(
    data_group_id=123,
    params=mp.UpdateLookupTableParams(name="Renamed Table"),
)
mp lookup-tables update --data-group-id 123 --name "Renamed Table"

Delete Lookup Tables

# Delete one or more lookup tables
ws.delete_lookup_tables(data_group_ids=[123, 456])
mp lookup-tables delete --data-group-ids "123,456"

Download a Lookup Table

# Download as raw CSV bytes
csv_data = ws.download_lookup_table(data_group_id=123)

# Save to file
with open("output.csv", "wb") as f:
    f.write(csv_data)

# Download with row limit
csv_data = ws.download_lookup_table(data_group_id=123, limit=100)
# Download to stdout
mp lookup-tables download --data-group-id 123

# Save to file
mp lookup-tables download --data-group-id 123 > output.csv

Advanced: Upload and Download URLs

For manual upload workflows or integration with external tools:

# Get a signed upload URL
url_info = ws.get_lookup_upload_url(content_type="text/csv")
print(url_info.url)  # Signed GCS URL

# Check async upload status
status = ws.get_lookup_upload_status("upload-id-123")
print(status)

# Get a signed download URL
download_url = ws.get_lookup_download_url(data_group_id=123)
print(download_url)
# Get upload URL
mp lookup-tables upload-url

# Get download URL
mp lookup-tables download-url --data-group-id 123

Schema Registry

Manage JSON Schema Draft 7 definitions in Mixpanel's schema registry. Schemas define the expected structure of events, custom events, and profiles.

List Schema Entries

import mixpanel_data as mp

ws = mp.Workspace()

# List all schemas
schemas = ws.list_schema_registry()
for s in schemas:
    print(f"{s.entity_type}/{s.name}: v{s.version}")

# Filter by entity type
event_schemas = ws.list_schema_registry(entity_type="event")
mp schemas list
mp schemas list --entity-type event
mp schemas list --format table

Create a Schema

result = ws.create_schema(
    entity_type="event",
    entity_name="Purchase",
    schema_json={
        "properties": {
            "amount": {"type": "number"},
            "currency": {"type": "string"},
        },
        "required": ["amount"],
    },
)
mp schemas create --entity-type event --entity-name "Purchase" \
    --schema-json '{"properties": {"amount": {"type": "number"}}}'

Bulk Create Schemas

params = mp.BulkCreateSchemasParams(
    entries=[
        mp.SchemaEntry(
            name="Login",
            entity_type="event",
            schema_definition={"properties": {"method": {"type": "string"}}},
        ),
        mp.SchemaEntry(
            name="Signup",
            entity_type="event",
            schema_definition={"properties": {"source": {"type": "string"}}},
        ),
    ],
    truncate=False,
    entity_type="event",
)
result = ws.create_schemas_bulk(params)
print(f"Added: {result.added}, Deleted: {result.deleted}")
mp schemas create-bulk \
    --entries-json '[{"name": "Login", "entityType": "event", "schemaDefinition": {"properties": {"method": {"type": "string"}}}}]'

# With truncate (replaces all existing schemas of this type)
mp schemas create-bulk --entries-json '[...]' --truncate

Update a Schema (Merge Semantics)

result = ws.update_schema(
    entity_type="event",
    entity_name="Purchase",
    schema_json={
        "properties": {
            "discount_code": {"type": "string"},
        },
    },
)
mp schemas update --entity-type event --entity-name "Purchase" \
    --schema-json '{"properties": {"discount_code": {"type": "string"}}}'

Bulk Update Schemas

params = mp.BulkCreateSchemasParams(
    entries=[
        mp.SchemaEntry(
            name="Login",
            entity_type="event",
            schema_definition={"properties": {"ip_address": {"type": "string"}}},
        ),
    ],
    entity_type="event",
)
results = ws.update_schemas_bulk(params)
for r in results:
    print(f"{r.name}: {r.status}")
mp schemas update-bulk --entries-json '[{"name": "Login", "entityType": "event", "schemaDefinition": {...}}]'

Delete Schemas

Destructive Operation

Schema deletion is irreversible. The CLI prompts for confirmation before proceeding.

# Delete a specific schema
result = ws.delete_schemas(entity_type="event", entity_name="Purchase")
print(f"Deleted: {result.delete_count}")

# Delete all schemas of a type
result = ws.delete_schemas(entity_type="event")
mp schemas delete --entity-type event --entity-name "Purchase"
mp schemas delete --entity-type event

Schema Enforcement

Configure how Mixpanel handles events that don't match defined schemas. Enforcement actions include "Warn and Accept", "Warn and Hide", and "Warn and Drop".

Get Enforcement Settings

config = ws.get_schema_enforcement()
print(f"State: {config.state}")
print(f"Rule: {config.rule_event}")

# Get specific fields only
config = ws.get_schema_enforcement(fields="state,ruleEvent")
mp lexicon enforcement get
mp lexicon enforcement get --fields "state,ruleEvent"
mp lexicon enforcement get --format table

Initialize Enforcement

result = ws.init_schema_enforcement(
    mp.InitSchemaEnforcementParams(rule_event="Warn and Accept"),
)
mp lexicon enforcement init --rule-event "Warn and Accept"

Update Enforcement (PATCH)

result = ws.update_schema_enforcement(
    mp.UpdateSchemaEnforcementParams(
        rule_event="Warn and Drop",
        notification_emails=["data-team@example.com"],
    ),
)
mp lexicon enforcement update \
    --params-json '{"ruleEvent": "Warn and Drop", "notificationEmails": ["data-team@example.com"]}'

Replace Enforcement (PUT)

Full Replacement

PUT semantics replace the entire enforcement configuration. All fields must be provided. The CLI prompts for confirmation.

result = ws.replace_schema_enforcement(
    mp.ReplaceSchemaEnforcementParams(
        events=[],
        common_properties=[],
        user_properties=[],
        rule_event="Warn and Hide",
        notification_emails=["admin@example.com"],
    ),
)
mp lexicon enforcement replace \
    --params-json '{"events": [], "commonProperties": [], "userProperties": [], "ruleEvent": "Warn and Hide", "notificationEmails": ["admin@example.com"]}'

Delete Enforcement

Destructive Operation

Deleting enforcement configuration is irreversible. The CLI prompts for confirmation.

result = ws.delete_schema_enforcement()
mp lexicon enforcement delete

Data Auditing

Audit your project's data against defined schemas to find violations such as unexpected events, missing properties, or type mismatches.

Run Full Audit

audit = ws.run_audit()
print(f"Computed at: {audit.computed_at}")
for v in audit.violations:
    print(f"  [{v.violation_type}] {v.event_name}: {v.description}")
mp lexicon audit
mp lexicon audit --format table

Run Events-Only Audit

A faster variant that only audits event schemas, skipping property-level checks.

audit = ws.run_audit_events_only()
for v in audit.violations:
    print(f"  {v.event_name}: {v.description}")
mp lexicon audit --events-only

Data Volume Anomalies

Monitor and manage anomalies detected in data volume patterns. Anomalies indicate unexpected spikes or drops that may signal tracking issues or data pipeline problems.

List Anomalies

# List all anomalies
anomalies = ws.list_data_volume_anomalies()
for a in anomalies:
    print(f"{a.event_name}: {a.status} (variance: {a.variance})")

# Filter by status
open_anomalies = ws.list_data_volume_anomalies(
    query_params={"status": "open"},
)
mp lexicon anomalies list
mp lexicon anomalies list --status open
mp lexicon anomalies list --event-name "Purchase" --format table

Update an Anomaly

result = ws.update_anomaly(
    mp.UpdateAnomalyParams(
        id=123,
        status="dismissed",
        anomaly_class="Event",
    ),
)
mp lexicon anomalies update --id 123 --status dismissed --anomaly-class Event

Bulk Update Anomalies

result = ws.bulk_update_anomalies(
    mp.BulkUpdateAnomalyParams(
        anomalies=[
            mp.BulkAnomalyEntry(id=1, anomaly_class="Event"),
            mp.BulkAnomalyEntry(id=2, anomaly_class="Event"),
        ],
        status="dismissed",
    ),
)
mp lexicon anomalies bulk-update \
    --params-json '{"anomalies": [{"id": 1, "anomalyClass": "Event"}, {"id": 2, "anomalyClass": "Event"}], "status": "dismissed"}'

Event Deletion Requests

Submit and manage requests to delete event data by event name, date range, and optional property filters.

Destructive Operation

Event deletion is irreversible. Use preview to validate filters before creating a deletion request.

List Deletion Requests

requests = ws.list_deletion_requests()
for r in requests:
    print(f"#{r.id}: {r.event_name} ({r.status})")
mp lexicon deletion-requests list
mp lexicon deletion-requests list --format table

Preview Deletion Filters

Preview what events would be affected before submitting a deletion request. This is a read-only operation with no side effects.

preview = ws.preview_deletion_filters(
    mp.PreviewDeletionFiltersParams(
        event_name="Test Event",
        from_date="2026-01-01",
        to_date="2026-01-31",
    ),
)
for item in preview:
    print(item)
mp lexicon deletion-requests preview \
    --event-name "Test Event" \
    --from-date 2026-01-01 --to-date 2026-01-31

Create a Deletion Request

result = ws.create_deletion_request(
    mp.CreateDeletionRequestParams(
        event_name="Test Event",
        from_date="2026-01-01",
        to_date="2026-01-31",
    ),
)
# Returns updated list of all deletion requests
for r in result:
    print(f"#{r.id}: {r.status}")
mp lexicon deletion-requests create \
    --event-name "Test Event" \
    --from-date 2026-01-01 --to-date 2026-01-31

Cancel a Deletion Request

Only pending requests can be cancelled. The CLI prompts for confirmation.

result = ws.cancel_deletion_request(request_id=456)
mp lexicon deletion-requests cancel --id 456

Next Steps

  • API Reference — Workspace — Complete method signatures and docstrings
  • API Reference — Types — EventDefinition, DropFilter, CustomProperty, LookupTable, SchemaEntry, SchemaEnforcementConfig, AuditResponse, DataVolumeAnomaly, EventDeletionRequest, and all parameter types
  • CLI Reference — Full CLI command documentation
  • Entity Management — Manage dashboards, reports, cohorts, feature flags, experiments, alerts, annotations, and webhooks