The ActivitySmith Python library provides convenient access to the ActivitySmith API from Python applications.
See the API reference.
This package is available on PyPI:
pip install activitysmithAlternatively, install from source with:
python -m pip install .import os
from activitysmith import (
ActivitySmith,
action,
alert_badge,
alert_icon,
content_state,
metric,
)
activitysmith = ActivitySmith(
api_key=os.environ["ACTIVITYSMITH_API_KEY"],
)activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
)activitysmith.notifications.send(
title="Homepage ready",
message="Your agent finished the redesign.",
media="https://cdn.example.com/output/homepage-v2.png",
redirection="https://github.com/acme/web/pull/482",
)Send images, videos, or audio with your push notifications, press and hold to preview media directly from the notification, then tap through to open the linked content.
What will work:
- direct image URL:
.jpg,.png,.gif, etc. - direct audio file URL:
.mp3,.m4a, etc. - direct video file URL:
.mp4,.mov, etc. - URL that responds with a proper media
Content-Type, even if the path has no extension
Push notification redirection and actions are optional. Use them to open HTTPS URLs, run a specific iPhone Shortcut with shortcuts://run-shortcut?name=..., or trigger backend webhook workflows.
Webhooks are executed by the ActivitySmith backend.
activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
redirection="https://crm.example.com/customers/cus_9f3a1d", # Optional
actions=[ # Optional (max 4)
action(
title="Open CRM Profile",
type="open_url",
url="https://crm.example.com/customers/cus_9f3a1d",
),
action(
title="Chat with Jarvis",
type="open_url",
url="shortcuts://run-shortcut?name=Jarvis",
),
action(
title="Start Onboarding Workflow",
type="webhook",
url="https://hooks.example.com/activitysmith/onboarding/start",
method="POST",
body={
"customer_id": "cus_9f3a1d",
"plan": "pro",
},
),
],
)There are five types of Live Activities:
stats: best for showing business numbers side by side, such as revenue, sales, new users, conversion, refunds, or any other value you want visible at a glancemetrics: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error ratesegmented_progress: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runsprogress: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploadsalert: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
Use a stable stream_key to identify the metric, job, deployment, or system you want to keep visible. The first stream(...) call starts the Live Activity. Later calls with the same stream_key update it.
activitysmith.live_activities.stream(
"sales-hourly",
content_state=content_state(
title="Sales",
subtitle="last hour",
type="stats",
metrics=[
metric(label="Revenue", value="$2430", color="blue"),
metric(label="Orders", value="37", color="green"),
metric(label="Conversion", value="4.8%", color="magenta"),
metric(label="Avg Order", value="$65.68", color="yellow"),
metric(label="Refunds", value="$84", color="red"),
metric(label="New Buyers", value="18", color="cyan"),
],
),
)activitysmith.live_activities.stream(
"prod-web-1",
content_state=content_state(
title="Server Health",
subtitle="prod-web-1",
type="metrics",
metrics=[
metric(label="CPU", value=9, unit="%"),
metric(label="MEM", value=45, unit="%"),
],
),
)activitysmith.live_activities.stream(
"nightly-backup",
content_state=content_state(
title="Nightly Backup",
subtitle="upload archive",
type="segmented_progress",
number_of_steps=3,
current_step=2,
),
)activitysmith.live_activities.stream(
"search-reindex",
content_state=content_state(
title="Search Reindex",
subtitle="catalog-v2",
type="progress",
percentage=42,
),
)activitysmith.live_activities.stream(
"customer-ops",
content_state=content_state(
title="Reactivation",
message="Lumen came back after 2 weeks",
type="alert",
icon=alert_icon("cloud.sun", color="yellow"),
badge=alert_badge("Customer", color="magenta"),
),
)Call end_stream(...) with the same stream_key to dismiss the Live Activity. You can include final values before it is removed. By default, iOS removes the Live Activity after two minutes. Set auto_dismiss_minutes to choose a different dismissal time, including 0 for immediate dismissal.
activitysmith.live_activities.end_stream(
"prod-web-1",
content_state=content_state(
title="Server Health",
subtitle="prod-web-1",
type="metrics",
metrics=[
metric(label="CPU", value=7, unit="%"),
metric(label="MEM", value=38, unit="%"),
],
auto_dismiss_minutes=2,
),
)Live Activities can include one optional action button.
open_url: open an HTTPS URL.open_urlwith ashortcuts://run-shortcut?name=...URL: run a specific iPhone Shortcut, for example to open an app.webhook: trigger a backend GET/POST workflow.
activitysmith.live_activities.stream(
"prod-web-1",
content_state=content_state(
title="Server Health",
subtitle="prod-web-1",
type="metrics",
metrics=[
metric(label="CPU", value=76, unit="%"),
metric(label="MEM", value=52, unit="%"),
],
),
action=action(
title="Dashboard",
type="open_url",
url="https://ops.example.com/servers/prod-web-1",
),
)activitysmith.live_activities.stream(
"deploy-payments-api",
content_state=content_state(
title="Deploying payments-api",
subtitle="Running database migrations",
type="segmented_progress",
number_of_steps=5,
current_step=3,
),
action=action(
title="Chat with Jarvis",
type="open_url",
url="shortcuts://run-shortcut?name=Jarvis",
),
)activitysmith.live_activities.stream(
"search-reindex",
content_state=content_state(
title="Reindexing product search",
subtitle="Shard 7 of 12",
type="segmented_progress",
number_of_steps=12,
current_step=7,
),
action=action(
title="Pause Reindex",
type="webhook",
url="https://ops.example.com/hooks/search/reindex/pause",
method="POST",
body={
"job_id": "reindex-2026-03-19",
"requested_by": "activitysmith-python",
},
),
)Add more context to Live Activities with icons and badges.
Supported Live Activity types: stats, metrics, progress, segmented_progress, and alert.
activitysmith.live_activities.stream(
"prod-web-1",
content_state=content_state(
title="Server Health",
subtitle="prod-web-1",
type=activitysmith.live_activities.TYPE_METRICS,
icon=alert_icon("server.rack", color="blue"),
metrics=[
metric(label="CPU", value=18, unit="%"),
metric(label="MEM", value=42, unit="%"),
],
),
)The icon.symbol value is an Apple SF Symbol name. Browse the catalog with one of these tools:
- ActivitySmith app - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
- SF Symbols - Apple's official macOS app
- Interactful - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
Badges are supported by alert, progress, and segmented_progress Live Activities.
activitysmith.live_activities.stream(
"nightly-database-backup",
content_state=content_state(
title="Nightly Database Backup",
subtitle="verify restore",
type=activitysmith.live_activities.TYPE_PROGRESS,
badge=alert_badge("S3", color="cyan"),
percentage=62,
),
)Choose from these colors for the Live Activity accent, including progress bars and action buttons, or apply them to an individual icon or badge:
lime, green, cyan, blue, purple, magenta, red, orange, yellow, gray
Channels are used to target specific team members or devices. Can be used for both push notifications and live activities.
activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
channels=["sales", "customer-success"], # Optional
)ActivitySmith lets you display any value on your Lock Screen with widgets - SaaS metrics, revenue, signups, uptime, habits, or anything else you want to track. Create a metric in the web app, then update the metric value using our API, add a widget to your lock screen and it will fetch the latest update automatically.
activitysmith.metrics.update("deploy.success_rate", 99.9)String metric values work too.
activitysmith.metrics.update("prod.status", "healthy")try:
activitysmith.notifications.send(
title="New subscription 💸",
)
except Exception as err:
print("Request failed:", err)Request/response models are included and can be imported from activitysmith_openapi.models.
- Python 3.9 or newer
MIT












