Entity Management¶
Manage Mixpanel dashboards, reports (bookmarks), cohorts, feature flags, experiments, alerts, annotations, and webhooks programmatically. Full CRUD operations with bulk support. For data governance operations (Lexicon definitions, drop filters, custom properties, custom events, and lookup tables), see the Data Governance guide.
Prerequisites
Entity management requires authentication — service account or OAuth credentials.
Scoping differs by entity type:
- Dashboards, reports, cohorts, alerts, annotations, webhooks require a workspace ID — set via
MP_WORKSPACE_IDenv var,--workspace-idCLI flag, orws.set_workspace_id(). Find yours withmp inspect infoorws.info(). - Feature flags and experiments are project-scoped and do NOT require a workspace ID.
Dashboards¶
List Dashboards¶
Create a Dashboard¶
Get, Update, Delete¶
Favorites and Pins¶
Add a Report to a Dashboard¶
Remove a Report from a Dashboard¶
Blueprint Dashboards¶
Create dashboards from pre-built templates:
# List available templates
templates = ws.list_blueprint_templates()
for t in templates:
print(f"{t.title_key}: {t.number_of_reports} reports")
# Create from template
dash = ws.create_blueprint(template_type="product_analytics")
# Configure and finalize
config = ws.get_blueprint_config(dash.id)
ws.finalize_blueprint(mp.BlueprintFinishParams(
dashboard_id=dash.id,
cards=config.cards,
))
Advanced Dashboard Operations¶
# Create an RCA (Root Cause Analysis) dashboard
rca_dash = ws.create_rca_dashboard(mp.CreateRcaDashboardParams(
rca_source_id=123,
rca_source_data=mp.RcaSourceData(source_type="metric"),
))
# Get ERF metrics
erf = ws.get_dashboard_erf(dashboard_id=123)
# Update dashboard components
ws.update_report_link(
dashboard_id=123,
report_link_id=456,
params=mp.UpdateReportLinkParams(link_type="embedded"),
)
ws.update_text_card(
dashboard_id=123,
text_card_id=789,
params=mp.UpdateTextCardParams(markdown="## Updated Header"),
)
Reports (Bookmarks)¶
Reports in Mixpanel are stored as "bookmarks". Each bookmark has a type (insights, funnels, flows, retention, etc.) and a params JSON object defining the query.
List Reports¶
# List all reports
reports = ws.list_bookmarks_v2()
# Filter by type
insights = ws.list_bookmarks_v2(bookmark_type="insights")
funnels = ws.list_bookmarks_v2(bookmark_type="funnels")
# Filter by IDs
specific = ws.list_bookmarks_v2(ids=[123, 456])
for r in reports:
print(f"{r.id}: {r.name} ({r.bookmark_type})")
Create a Report¶
Get, Update, Delete¶
# Get
report = ws.get_bookmark(123)
# Update
updated = ws.update_bookmark(123, mp.UpdateBookmarkParams(
name="Daily Signups v2",
description="Updated tracking",
))
# Delete
ws.delete_bookmark(123)
# Bulk operations
ws.bulk_delete_bookmarks([123, 456])
ws.bulk_update_bookmarks([
mp.BulkUpdateBookmarkEntry(id=123, name="Renamed Report"),
mp.BulkUpdateBookmarkEntry(id=456, description="Updated desc"),
])
Report History and Dashboard Links¶
# View change history
history = ws.get_bookmark_history(bookmark_id=123)
for entry in history.data:
print(entry)
# Paginate through history
history = ws.get_bookmark_history(bookmark_id=123, page_size=10)
if history.pagination.has_more:
next_page = ws.get_bookmark_history(
bookmark_id=123,
cursor=history.pagination.cursor,
)
# Find which dashboards contain this report
dashboard_ids = ws.bookmark_linked_dashboard_ids(bookmark_id=123)
Cohorts¶
List Cohorts¶
Create a Cohort¶
Get, Update, Delete¶
# Get
cohort = ws.get_cohort(123)
# Update
updated = ws.update_cohort(123, mp.UpdateCohortParams(
name="Super Users",
description="Updated criteria",
))
# Delete
ws.delete_cohort(123)
# Bulk operations
ws.bulk_delete_cohorts([123, 456])
ws.bulk_update_cohorts([
mp.BulkUpdateCohortEntry(id=123, name="Renamed Cohort"),
mp.BulkUpdateCohortEntry(id=456, description="Updated"),
])
Feature Flags¶
Feature flags are project-scoped — no workspace ID required. They use UUID string IDs (not integer IDs like dashboards/reports/cohorts).
PUT Semantics
Feature flag update uses full replacement (PUT semantics). All required fields (name, key, status, ruleset) must be provided on every update — even if you're only changing one field.
List Feature Flags¶
Create a Feature Flag¶
Get, Update, Delete¶
# Get a flag by UUID
flag = ws.get_feature_flag("abc-123-uuid")
# Update (PUT — all required fields must be provided)
updated = ws.update_feature_flag("abc-123-uuid", mp.UpdateFeatureFlagParams(
name="Dark Mode",
key="dark_mode",
status=mp.FeatureFlagStatus.ENABLED,
ruleset=flag.ruleset, # Must provide complete ruleset
))
# Delete
ws.delete_feature_flag("abc-123-uuid")
Archive, Restore, Duplicate¶
Test Users and History¶
# Assign test users to specific variants
ws.set_flag_test_users("abc-123-uuid", mp.SetTestUsersParams(
users={"On": "user-1", "Off": "user-2"}
))
# View change history
history = ws.get_flag_history("abc-123-uuid")
print(f"{history.count} changes")
# Check account limits
limits = ws.get_flag_limits()
print(f"Using {limits.current_usage}/{limits.limit} flags")
Experiments¶
Experiments are project-scoped — no workspace ID required. They have a distinct lifecycle with managed state transitions:
PATCH Semantics
Experiment update uses partial update (PATCH semantics). Only provide the fields you want to change.
List Experiments¶
Create an Experiment¶
Get, Update, Delete¶
Experiment Lifecycle¶
The key differentiator of experiments: a managed lifecycle with state transitions.
# 1. Create (starts in Draft)
exp = ws.create_experiment(mp.CreateExperimentParams(
name="Pricing Page Test"
))
# 2. Launch (Draft → Active)
launched = ws.launch_experiment(exp.id)
# 3. Conclude (Active → Concluded)
concluded = ws.conclude_experiment(exp.id)
# Or with an explicit end date:
concluded = ws.conclude_experiment(
exp.id,
params=mp.ExperimentConcludeParams(end_date="2026-04-01"),
)
# 4. Decide (Concluded → Success or Fail)
decided = ws.decide_experiment(exp.id, mp.ExperimentDecideParams(
success=True,
variant="simplified",
message="15% conversion lift confirmed",
))
# Launch
mp experiments launch xyz-456-uuid
# Conclude
mp experiments conclude xyz-456-uuid
mp experiments conclude xyz-456-uuid --end-date 2026-04-01
# Decide as success
mp experiments decide xyz-456-uuid --success \
--variant simplified --message "15% conversion lift confirmed"
# Decide as failure
mp experiments decide xyz-456-uuid --no-success \
--message "No significant difference"
Archive, Restore, Duplicate¶
ERF Experiments¶
List experiments in ERF (Experiment Results Framework) format:
Alerts¶
Custom alerts monitor saved reports and notify when conditions are met. Alerts are workspace-scoped and linked to bookmarks (saved reports).
List Alerts¶
Create an Alert¶
alert = ws.create_alert(mp.CreateAlertParams(
bookmark_id=12345,
name="Daily signups drop",
condition={
"keys": [{"header": "Signup", "value": "Signup"}],
"type": "absolute",
"op": "<",
"value": 100,
},
frequency=mp.AlertFrequencyPreset.DAILY,
paused=False,
subscriptions=[{"type": "email", "value": "team@example.com"}],
))
print(f"Created alert {alert.id}: {alert.name}")
Get, Update, Delete¶
Monitoring¶
# Check alert count and limits
count = ws.get_alert_count()
print(f"{count.anomaly_alerts_count}/{count.alert_limit} alerts")
# View trigger history (paginated)
history = ws.get_alert_history(42, page_size=10)
for entry in history.results:
print(entry)
# Send a test notification
result = ws.test_alert(mp.CreateAlertParams(
bookmark_id=12345,
name="Test",
condition={"type": "absolute", "op": "<", "value": 100},
frequency=86400,
paused=False,
subscriptions=[{"type": "email", "value": "me@example.com"}],
))
# Get screenshot URL
screenshot = ws.get_alert_screenshot_url("gcs-key-here")
print(screenshot.signed_url)
# Alert count and limits
mp alerts count
# Trigger history
mp alerts history 42 --page-size 10
# Test notification
mp alerts test \
--bookmark-id 12345 \
--name "Test" \
--condition '{"type": "absolute", "op": "<", "value": 100}' \
--frequency 86400 \
--subscriptions '[{"type": "email", "value": "me@example.com"}]'
# Screenshot URL
mp alerts screenshot --gcs-key "gcs-key-here"
Validate Alerts¶
Check whether alerts are compatible with a bookmark configuration:
Annotations¶
Timeline annotations mark important events (releases, incidents, campaigns) on your Mixpanel charts.
List Annotations¶
import mixpanel_data as mp
ws = mp.Workspace()
# List all annotations
annotations = ws.list_annotations()
# Filter by date range
annotations = ws.list_annotations(
from_date="2025-01-01",
to_date="2025-03-31",
)
# Filter by tags
annotations = ws.list_annotations(tags=[1, 2])
for ann in annotations:
print(f"{ann.date}: {ann.description}")
Create an Annotation¶
Date Format
Annotation dates must use %Y-%m-%d %H:%M:%S format (e.g., "2025-03-31 00:00:00").
Get, Update, Delete¶
Immutable Date
The annotation date cannot be changed after creation. Only description and tags are updatable.
Annotation Tags¶
Organize annotations with tags:
Webhooks¶
Project webhooks receive HTTP notifications when events occur in your Mixpanel project.
List Webhooks¶
Create a Webhook¶
result = ws.create_webhook(mp.CreateWebhookParams(
name="Pipeline webhook",
url="https://example.com/webhook",
))
print(f"Created webhook {result.id}")
# With basic auth
result = ws.create_webhook(mp.CreateWebhookParams(
name="Authenticated webhook",
url="https://example.com/webhook",
auth_type=mp.WebhookAuthType.BASIC,
username="user",
password="secret",
))
Update, Delete¶
Test Connectivity¶
Next Steps¶
- API Reference — Workspace — Complete method signatures and docstrings
- API Reference — Types — Dashboard, Bookmark, Cohort, Feature Flag, Experiment, Alert, Annotation, and Webhook type definitions
- CLI Reference — Full CLI command documentation
- Data Governance Guide — Manage Lexicon definitions, drop filters, custom properties, custom events, and lookup tables