# API Keys
Source: https://activitysmith.com/docs/api-keys
Create and manage API keys
API Keys are secret tokens used to authenticate your requests. They are unique to your account and should be kept confidential.
## Create an API Key
To create an API key, go to the [API Keys](https://activitysmith.com/app/keys) page and click the **Create API Key** button.
1. Click **Create API Key**.
2. Give your API Key a name (maximum 100 characters).
3. Select **All Recipients** or **Channel Scoped** as the Scope.
4. If you select **Channel Scoped**, you can choose the channels you want to restrict access to.
For security reasons, you can only view the API Key once.
## API Key Scopes
There are two different API Key Scopes you can choose from:
* **All Recipients**: The API key can target all recipients in the account.
* **Channel Scoped**: The API key is restricted to channels assigned to that key.
You can configure scope when creating or editing a key on the [API Keys](https://activitysmith.com/app/keys) page.
## Edit API Key details
After creating an API Key, you can edit the following details:
* Name
* Scope
* Scope Channels (only available if Scope is **Channel Scoped**)
To edit an API Key, click the **Edit API Key** button.
## View all API Keys
To manage your API keys, go to the [API Keys](https://activitysmith.com/app/keys) page. The page shows you all the API Keys you have created along with their details
## Scope behavior with `target.channels`
* Scope `all` + no `target.channels`: sends to all recipients in your account.
* Scope `all` + `target.channels`: sends only to the provided channel slugs.
* Scope `channels` + no `target.channels`: sends to channels assigned to that API key.
* Scope `channels` + `target.channels`: requested channel slugs must be a subset of channels assigned to that API key.
Channels in request payloads use channel slugs, for example, `["marketing", "test-devices"]`.
## Scope enforcement and errors
If a channel-scoped key (`channels`) tries to target channel slugs outside its assignment, the request fails with `403 Forbidden` and a clear scope-violation error message.
Use the [channels guide](/docs/channels) for channel setup and targeting examples.
# End Live Activity
Source: https://activitysmith.com/docs/api-reference/endpoint/live-activity-end
POST /live-activity/end
Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities only.
Use this manual lifecycle endpoint only when you need direct control over a
specific Live Activity instance. For new integrations, prefer
[`DELETE /live-activity/stream/{stream_key}`](/docs/api-reference/endpoint/live-activity-stream).
This endpoint ends an existing Live Activity by `activity_id`.
* `metrics`: send the final `metrics` array if you want the ended state to show final values.
* `stats`: send the final `metrics` array if you want the ended state to show final labeled values.
* `segmented_progress`: send the final `current_step` and optionally the latest `number_of_steps`.
* `progress`: send the final `percentage`, or `value` with `upper_limit`.
* `timer`: leave `duration_seconds` out if you want the ended state to preserve the current timer value.
* `action` is optional if you want the ended state to keep showing a button before dismissal.
* `auto_dismiss_minutes` is optional if you want to control how long the ended Live Activity stays visible.
For `segmented_progress`, the final payload can include an updated
`number_of_steps` as well as the final `current_step`. The step count does not
need to match the value used when the activity started.
# Start Live Activity
Source: https://activitysmith.com/docs/api-reference/endpoint/live-activity-start
POST /live-activity/start
Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities only.
Use this manual lifecycle endpoint only when you need direct control over a
specific Live Activity instance. For new integrations, prefer
[`PUT /live-activity/stream/{stream_key}`](/docs/api-reference/endpoint/live-activity-stream).
This endpoint creates a new Live Activity and returns an `activity_id`. You will
use that same ID for later update and end calls.
* `metrics`: send `title`, `type`, and a non-empty `metrics` array.
* `stats`: send `title`, `type`, and a non-empty `metrics` array for up to 8 labeled values.
* `segmented_progress`: send `title`, `type`, `number_of_steps`, and `current_step`.
* `progress`: send `title`, `type`, and either `percentage` or `value` with `upper_limit`.
* `timer`: send `title`, `type`, and `duration_seconds` for a countdown. To start at 00:00 and count up, set `counts_down` to `false` and leave out `duration_seconds`.
* `action` is optional if you want the Live Activity to show one button that opens a URL or triggers a webhook.
* `target.channels` is optional if you want to scope delivery to specific channel slugs.
For `segmented_progress`, `number_of_steps` is not fixed for the full lifecycle.
You can change it later in update or end calls if the workflow adds or removes
steps.
# Live Activity Stream
Source: https://activitysmith.com/docs/api-reference/endpoint/live-activity-stream
PUT /live-activity/stream/{stream_key}
Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. For timer streams, send duration_seconds to start or reset the timer; omit duration_seconds on later updates to preserve the existing timer window. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities only.
Use this endpoint when you want ActivitySmith to manage the Live Activity for
you.
* Send the latest state for a stable `stream_key`.
* If the Live Activity does not exist yet, ActivitySmith starts it.
* If it already exists, ActivitySmith updates it.
* You do not need to keep local state between updates.
* For `timer`, send `duration_seconds` for countdowns. To start at 00:00 and count up, set `counts_down` to `false` and leave out `duration_seconds`.
* Later `timer` updates can change visible fields without sending `duration_seconds`.
This is a good fit for cron jobs, scheduled tasks, CI workflows, monitoring
jobs, and background workers that only know the latest state.
To stop a managed stream, use
[`DELETE /live-activity/stream/{stream_key}`](/docs/api-reference/endpoint/live-activity-stream-end).
# End Live Activity Stream
Source: https://activitysmith.com/docs/api-reference/endpoint/live-activity-stream-end
DELETE /live-activity/stream/{stream_key}
Use this endpoint when the process you are tracking is finished and you no longer want the Live Activity on your devices. ActivitySmith ends the current Live Activity for this stream and dismisses it from devices. If you need direct lifecycle control, use /live-activity/start, /live-activity/update, and /live-activity/end instead. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities only.
Use this endpoint when the process you are tracking is finished and you want to
dismiss the managed Live Activity stream.
* Call it with the same `stream_key` you used for stream updates.
* You can include optional `content_state` with final values.
* 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.
# Update Live Activity
Source: https://activitysmith.com/docs/api-reference/endpoint/live-activity-update
POST /live-activity/update
Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. For timer activities, send duration_seconds only when you want to reset the timer window; omit it to keep the current timer running. Use secondary_action for a second button on alert, progress, and segmented_progress Live Activities only.
Use this manual lifecycle endpoint only when you need direct control over a
specific Live Activity instance. For new integrations, prefer
[`PUT /live-activity/stream/{stream_key}`](/docs/api-reference/endpoint/live-activity-stream).
This endpoint updates an existing Live Activity by `activity_id`.
* `metrics`: send the latest `metrics` array.
* `stats`: send the latest `metrics` array for up to 8 labeled values.
* `segmented_progress`: send the latest `current_step` and, if needed, an updated `number_of_steps`.
* `progress`: send the latest `percentage`, or `value` with `upper_limit`.
* `timer`: update visible fields such as `title`, `subtitle`, or `color`. Leave `duration_seconds` out unless you want to change the timer.
* `action` is optional if you want to set or replace the Live Activity button.
* `type` is optional on update if the existing Live Activity already has a type.
For `segmented_progress`, you can update both `current_step` and
`number_of_steps`. Use this when the workflow gains or loses steps after the
activity has already started.
# Update Metric Value
Source: https://activitysmith.com/docs/api-reference/endpoint/metric-value-update
POST /metrics/{key}/value
Updates the latest value for a metric displayed in ActivitySmith widgets. Create the metric in the web app first, then update its value using the key.
# Send Push Notification
Source: https://activitysmith.com/docs/api-reference/endpoint/push-notification
POST /push-notification
Sends a push notification to devices matched by API key scope and optional target channels. Supports optional redirection URL, optional media preview or playback when the notification is expanded, and up to 4 interactive actions. `media` cannot be combined with `actions`.
# Introduction
Source: https://activitysmith.com/docs/api-reference/introduction
ActivitySmith API reference
## Features
Send a push notification to all of your paired devices.
Start, update, and dismiss a Live Activity stream.
Update metric values shown in ActivitySmith widgets.
## Base URL
All requests contain the following base URL:
```bash theme={null}
https://activitysmith.com/api/
```
## Authentication
For authentication, it's required to include an Authorization header. The header should contain `Bearer ask_123456789`, where `ask_123456789` represents your [API Key](/docs/api-keys).
```bash theme={null}
Authorization: Bearer ask_123456789
```
## Response codes
ActivitySmith employs conventional HTTP status codes to signify the outcome of your requests.
Typically, 2xx HTTP status codes denote success, 4xx codes represent failures related to the user, and 5xx codes signal infrastructure problems.
| Status | Description |
| ------ | -------------------------------------------- |
| 200 | Request was successful. |
| 400 | Verify the correctness of the parameters. |
| 401 | The API key is invalid or was not provided. |
| 404 | The requested resource could not be located. |
| 429 | The rate limit has been surpassed. |
| 5xx | Signifies a server error with ActivitySmith. |
Refer to the Error Codes section for a detailed explanation of all potential API errors.
## Channels
Channels let you target specific subsets of recipients instead of broadcasting to everyone in an account.
* Use channels when teams, environments, or workflows need separate delivery groups.
* Keep [API keys](/docs/api-keys) broad or channel-scoped depending on how strict you want targeting to be.
Read the full [channels guide](/docs/channels).
## Rate limit
The ActivitySmith API has a [rate limit](/docs/rate-limits) to ensure the stability and reliability of the service. The rate limit is applied to all endpoints and is based on the number of requests made within a specific time frame.
When you exceed the rate limit, you will receive a 429 response code.
# Channels
Source: https://activitysmith.com/docs/channels
Use channels to target specific users and devices.
Channels let you target specific groups of recipients instead of sending to everyone in an account.
Common use case:
* Different teams should receive different notifications (for example, `marketing`, `developers`, `devops`, `sre`).
Channels are flexible:
* You can assign users, devices, or both to a channel.
* You can choose channels per request using `target.channels`.
* You can keep some [API key](/docs/api-keys) broad and scope other [API key](/docs/api-keys) to specific channels.
## How Targeting Works
Use channel slugs in `target.channels`:
```json theme={null}
{
"target": {
"channels": ["ios-beta", "ops"]
}
}
```
* If `target` is omitted and API key scope is `all`, delivery goes to all recipients in the account.
* If `target` is omitted and API key scope is `channels`, delivery goes to channels assigned to that [API key](/docs/api-keys).
* If `target.channels` is provided, only those channel slugs are targeted.
## Push Notifications
```json theme={null}
{
"title": "New subscription 💸",
"message": "Customer upgraded to Pro plan",
"target": {
"channels": ["ios-beta", "ops"]
}
}
```
## Live Activities
```json theme={null}
{
"content_state": {
"title": "Nightly database backup",
"number_of_steps": 3,
"current_step": 1,
"type": "segmented_progress"
},
"target": {
"channels": ["ios-beta", "ops"]
}
}
```
See endpoint docs for full request and response fields:
* [/api-reference/endpoint/push-notification](/docs/api-reference/endpoint/push-notification)
* [/api-reference/endpoint/live-activity-start](/docs/api-reference/endpoint/live-activity-start)
# Live Activity Colors
Source: https://activitysmith.com/docs/colors
Colors can be used to customize the appearance of your Live Activities. You can choose from the following colors(default is `blue`):
### `lime`
### `green`
### `cyan`
### `blue`
### `purple`
### `magenta`
### `red`
### `orange`
### `yellow`
# Inbound Webhooks
Source: https://activitysmith.com/docs/inbound-webhooks
Forward events from external services into Push Notifications and Live Activities.
Inbound webhooks let an external service POST events to ActivitySmith. Each event is turned into a Push Notification or a Live Activity on the paired iOS devices you target, with no backend code on your side.
Use inbound webhooks when you want lock-screen visibility into a service that already has its own webhook system, like CI runs, deploys, error alerts, or issue updates.
## How It Works
1. Generate an inbound webhook URL in the [Webhooks section](https://activitysmith.com/app/webhooks).
2. Paste it into the source service (GitHub, Vercel, Sentry, and so on) and pick the events you care about.
3. Choose how the event is delivered: Push Notification or Live Activity.
4. Map payload fields to the title, message, and metadata you want shown.
5. Optionally route the event to specific [channels](/docs/channels).
Each integration ships with ready-to-use presets that cover the most common events, so you can connect a source in a few clicks. Tweak any field on a preset, or start from scratch when you want full control over the title, body, action button, etc.
The same source service can drive multiple webhooks. For example, you can send production deploy events to a `#prod` channel as a Live Activity, and preview deploys to a `#previews` channel as a Push Notification.
## Delivery Options
Each webhook delivers events as one of:
* **Push Notification**: best for short, conclusive events like a check that failed, a PR that merged, or an alert that fired.
* **Live Activity**: best for long-running work like CI workflows or production deploys. The Live Activity stays on the lock screen while the job runs and dismisses when it finishes.
You can also attach an action button to the resulting notification or activity that opens the source service (the GitHub run, the Sentry issue, the Vercel deployment, and so on). See the [action button section](/docs/#action-button) on the quickstart for the field reference.
## Channel Routing
Inbound webhooks use the same [channels](/docs/channels) as the rest of the API. Route events from a webhook to one or more channel slugs so they reach the right people or devices.
## Secret Verification
ActivitySmith verifies inbound requests with a per-webhook secret. The source service must include the secret on every request as an HTTP header:
```
X-ActivitySmith-Webhook-Secret: YOUR_SECRET
```
Requests with a missing or wrong secret are rejected and logged in the delivery log so you can spot misconfigured sources.
Some integrations (like GitHub and Linear) sign their payloads with their own scheme. ActivitySmith verifies those signatures natively when you use the integration, so you do not need a separate secret.
## Delivery Log
Every webhook keeps a rolling log of recent requests. For each entry you can see:
* The raw incoming payload
* The mapped Push Notification or Live Activity that was sent
* Verification or mapping errors, if any
Use the log to debug new integrations, confirm a noisy source has been quieted down, or replay a payload while you tweak the field mapping.
## Available Integrations
Pre-built integrations handle event subscription, signature verification, and a default field mapping for you. You can override the mapping at any time.
| Integration | Supported events |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| [GitHub](https://activitysmith.com/integrations/github-webhooks) | [GitHub webhook events](https://docs.github.com/en/webhooks/webhook-events-and-payloads) |
| [GitLab](https://activitysmith.com/integrations/gitlab) | [GitLab webhook events](https://docs.gitlab.com/user/project/integrations/webhook_events/) |
| [Linear](https://activitysmith.com/integrations/linear) | [Linear webhook events](https://linear.app/developers/webhooks) |
| [Sentry](https://activitysmith.com/integrations/sentry) | [Sentry webhook events](https://docs.sentry.io/organization/integrations/integration-platform/webhooks/) |
| [Vercel](https://activitysmith.com/integrations/vercel) | [Vercel webhook events](https://vercel.com/docs/webhooks/webhooks-api) |
| [Netlify](https://activitysmith.com/integrations/netlify) | [Netlify deploy notifications](https://docs.netlify.com/deploy/deploy-notifications/) |
| [Railway](https://activitysmith.com/integrations/railway) | [Railway webhook events](https://docs.railway.com/guides/webhooks) |
The full integration list with setup guides lives at [activitysmith.com/integrations](https://activitysmith.com/integrations).
## Generic JSON
If the service you want to track is not on the list, use a generic JSON webhook. Send any JSON payload to your inbound URL, paste a sample into the dashboard, and map fields like `title`, `subtitle`, `body`, and `url` onto the resulting Push Notification or Live Activity. This works for internal services, cron jobs, or third-party tools that expose webhooks but do not have a dedicated ActivitySmith integration yet.
Need an integration that is not listed? Email [adam@activitysmith.com](mailto:adam@activitysmith.com).
# Quickstart
Source: https://activitysmith.com/docs/index
Send Live Activities and push notifications to your iOS devices from any backend
## Welcome to ActivitySmith
[ActivitySmith](https://activitysmith.com) is API service that lets you trigger and update Live Activities and send push notifications directly from your own infrastructure.
Pair your iOS device(s), authenticate with an [API key](/docs/api-keys), and send real-time alerts from any backend, cron, agent, or automation. Without building or maintaining your own iOS app or dealing directly with APNs.
Check out the following resources to get started:
* **API**: [Documentation](https://activitysmith.com/docs/api-reference/introduction)
* **SDKs**: [Node](https://activitysmith.com/docs/sdks/node), [Python](https://activitysmith.com/docs/sdks/python), [Go](https://activitysmith.com/docs/sdks/go), [PHP](https://activitysmith.com/docs/sdks/php), [Ruby](https://activitysmith.com/docs/sdks/ruby), [CLI](https://activitysmith.com/docs/sdks/cli)
* **Others**: [Zapier](https://zapier.com/apps/activitysmith/integrations)
Want an SDK or Integration? Let us know at [adam@activitysmith.com](mailto:adam@activitysmith.com).
### Prerequisites
* [Create an API key](https://activitysmith.com/app/keys)
* [Download our iOS app](https://apps.apple.com/us/app/activitysmith/id6752254835) and pair your device(s)
### Features
* [**Push Notifications**](#push-notifications): send push notifications to all paired devices or target specific channels.
* [**Live Activities**](#live-activities): start, update and end a Live Activity on your lock screen or dynamic island, with optional channel targeting and one optional action button.
* [**Widgets**](/docs/widgets): display any value on your Lock Screen with widgets - SaaS metrics, revenue, signups, uptime, habits, or anything else you want to track.
* [**Inbound Webhooks**](/docs/inbound-webhooks): forward events from external services such as Vercel, Netlify, Railway, and more, into Push Notifications and Live Activities.
### Powerful Capabilities
* **Glanceable observability**: monitor real-time system state and long-running operations directly on your lock screen or dynamic island.
* **The hard stuff**: APNs(Apple Push Notification service), certificates, orchestration
* **Customizability**: adapt the experience to fit your unique needs.
* **Works with any backend**: use with any backend, cron, agent, automation or AI tool.
* **iOS app**: ready to use native iOS app for your iPhone or iPad. No need to build your own.
## Push Notifications
To send a push notification, use the `push-notification` endpoint. It takes `title` and optional fields like `message`, `payload`, `media`, `redirection`, `actions`, and `target.channels`.\
`target.channels` accepts channel slugs (for example `["devs", "ops"]`).
* `media` attaches an image, audio file, or video that users can preview or play when they expand the notification.
* `redirection` opens an HTTPS URL or runs a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL on normal tap.
* `actions` (up to 4) appear when users expand the notification. `open_url` actions support HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs; `webhook` actions call your backend.
* `media + redirection` is supported.
* `media + actions` is not supported in v1.
```bash cURL theme={null}
curl -X POST https://activitysmith.com/api/push-notification \
-H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "New subscription 💸",
"message": "Customer upgraded to Pro plan"
}'
```
```js Node theme={null}
import ActivitySmith from "activitysmith";
const activitysmith = new ActivitySmith({
apiKey: process.env.ACTIVITYSMITH_API_KEY,
});
await activitysmith.notifications.send({
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
});
```
```python Python theme={null}
import os
from activitysmith import ActivitySmith
activitysmith = ActivitySmith(
api_key=os.environ.get("ACTIVITYSMITH_API_KEY", "YOUR-API-KEY")
)
activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
)
```
```go Go theme={null}
package main
import (
"log"
"os"
activitysmithsdk "github.com/ActivitySmithHQ/activitysmith-go"
)
func main() {
activitysmith, err := activitysmithsdk.New(os.Getenv("ACTIVITYSMITH_API_KEY"))
if err != nil {
log.Fatal(err)
}
input := activitysmithsdk.PushNotificationInput{
Title: "New subscription 💸",
Message: "Customer upgraded to Pro plan",
}
_, err := activitysmith.Notifications.Send(input)
if err != nil {
log.Fatal(err)
}
}
```
```php PHP theme={null}
notifications->send(
title: 'New subscription 💸',
message: 'Customer upgraded to Pro plan',
);
```
```ruby Ruby theme={null}
require "activitysmith"
activitysmith = ActivitySmith::Client.new(
api_key: ENV.fetch("ACTIVITYSMITH_API_KEY", "YOUR-API-KEY")
)
activitysmith.notifications.send(
{
title: "New subscription 💸",
message: "Customer upgraded to Pro plan"
}
)
```
```bash CLI theme={null}
activitysmith push \
--title "New subscription 💸" \
--message "Customer upgraded to Pro plan"
```
**Response**
```json theme={null}
{
"success": true,
"devices_notified": 3,
"users_notified": 1,
"timestamp": "2025-08-12T12:00:00.000Z"
}
```
## Live Activities
There are six types of Live Activities:
| Type | Best for | Required state |
| -------------------- | ----------------------------- | ------------------------------------------------------------------------------ |
| `stats` | up to 8 labeled values | `title`, `type`, and a non-empty `metrics` array |
| `metrics` | Live operational stats | `title`, `type`, and a non-empty `metrics` array |
| `segmented_progress` | Jobs tracked in steps | `title`, `type`, `number_of_steps`, `current_step` |
| `progress` | Jobs with continuous progress | `title`, `type`, and either `percentage` or `value` + `upper_limit` |
| `alert` | Focused status updates | `title`, `type`, and `message` |
| `timer` | Countdowns or elapsed runtime | `title`, `type`, and either `duration_seconds` or `counts_down` set to `false` |
### Start & Update Live Activity
Use stream updates to start, update, and dismiss Live Activities with a stable
`stream_key`.
* [`PUT /live-activity/stream/:stream_key`](/docs/stream)
* [`DELETE /live-activity/stream/:stream_key`](/docs/stream)
Send the latest state for a stable `stream_key`, and ActivitySmith starts or
updates the Live Activity. You do not need to keep local state between updates.
When the work is done, call `DELETE /live-activity/stream/:stream_key` 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.
### Action Button
Live Activities support one optional `action` button shown on the Lock Screen. Use it to have a one-tap path from a long-running
job to the place where you can act on it. The `action` field is accepted on
stream updates and works with all Live Activity types.
For `alert` Live Activities, set `content_state.color` to tint the action
button. `icon.color` and `badge.color` only affect the icon and badge.
There are two action types:
* `open_url`: opens an HTTPS URL or runs a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL.
* `webhook`: ActivitySmith's backend calls your HTTPS webhook with `GET` or `POST`.
The `action` object accepts:
| Field | Required | Description |
| -------- | ------------ | -------------------------------------------------------------------------------------------------------------------- |
| `title` | yes | Button label shown on the Live Activity. |
| `type` | yes | Either `open_url` or `webhook`. |
| `url` | yes | For `open_url`, use an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL. For `webhook`, use an HTTPS endpoint. |
| `method` | webhook only | `GET` or `POST`. |
| `body` | webhook only | Optional JSON payload sent with the webhook request. |
#### open\_url
Use `open_url` when the button should jump the user to a dashboard or run page
tied to the work. You can also use a `shortcuts://run-shortcut?name=...` URL to
run a specific iPhone Shortcut, for example to open an app on your iPhone.
```json theme={null}
{
"content_state": {
"title": "Deploying payments-api",
"subtitle": "Running database migrations",
"number_of_steps": 5,
"current_step": 3,
"type": "segmented_progress"
},
"action": {
"title": "Open Workflow",
"type": "open_url",
"url": "https://github.com/acme/payments-api/actions/runs/1234567890"
}
}
```
#### webhook
Use `webhook` when the button should trigger an action in your backend, like
pausing a job, acknowledging an alert, or canceling a workflow. ActivitySmith
calls the URL server-side, so the user does not leave the Lock Screen.
```json theme={null}
{
"content_state": {
"title": "Reindexing product search",
"subtitle": "Shard 7 of 12",
"number_of_steps": 12,
"current_step": 7,
"type": "segmented_progress"
},
"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"
}
}
}
```
Notes:
* Only HTTPS URLs are supported for both action types.
* One button per Live Activity.
* Pass `action` on an update call to set or replace the button on an active Live Activity.
## Channel Targeting
You can scope delivery with channel slugs:
```json theme={null}
{
"target": {
"channels": ["devs", "ops"]
}
}
```
* If `target` is omitted and API key scope is `all`: send to all account recipients.
* If `target` is omitted and API key scope is `channels`: send to channels assigned to that key.
* If `target.channels` is present: only those channel slugs are used.
# Live Activity Stream
Source: https://activitysmith.com/docs/live-activity-stream
Start, update, and dismiss Live Activities with a stable stream key.
Live Activity streams use a stable `stream_key` for the thing you want to keep
visible. Send the latest state to that key whenever the data changes.
* The first `PUT` starts the Live Activity.
* Next `PUT` request with the same `stream_key` updates it.
* `DELETE` ends the Live Activity when the work is done.
## What is a `stream_key`?
A `stream_key` is a stable name for one ongoing process.
Examples:
* `prod-web-1`
* `deployment-main`
* `nightly-backup`
* `ev-charging`
Use one `stream_key` for one system, workflow, or process.
## Example
```bash theme={null}
curl -X PUT https://activitysmith.com/api/live-activity/stream/prod-web-1 \
-H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content_state": {
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"metrics": [
{
"label": "CPU",
"value": 24,
"unit": "%"
},
{
"label": "MEM",
"value": 61,
"unit": "%"
}
]
}
}'
```
Call the same endpoint again with the same `stream_key` whenever the state
changes.
## Timer Example
Use `timer` when you need countdowns or timers.
```bash theme={null}
curl -X PUT https://activitysmith.com/api/live-activity/stream/benchmark-run \
-H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content_state": {
"title": "Benchmark Run",
"subtitle": "sampling",
"type": "timer",
"duration_seconds": 300,
"color": "cyan"
}
}'
```
For a countdown, send `duration_seconds`. You can update `title`, `subtitle`,
`color`, or any other visible field as the work changes. Leave
`duration_seconds` out unless you want to change the timer.
To start at 00:00 and count up, set `counts_down` to `false` and leave out
`duration_seconds`.
## End Live Activity
Use `DELETE /live-activity/stream/:stream_key` when the tracked process is
finished and you want 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.
```bash theme={null}
curl -X DELETE https://activitysmith.com/api/live-activity/stream/prod-web-1 \
-H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content_state": {
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"metrics": [
{
"label": "CPU",
"value": 7,
"unit": "%"
},
{
"label": "MEM",
"value": 38,
"unit": "%"
}
],
"auto_dismiss_minutes": 2
}
}'
```
`content_state` is optional here. Include it if you want one last update before the Live Activity is dismissed.
If you later send another `PUT` request with the same `stream_key`,
ActivitySmith starts a new Live Activity.
## Stream responses
Stream responses include an `operation` field:
* `started`: ActivitySmith started a new Live Activity for this `stream_key`
* `updated`: ActivitySmith updated the current Live Activity
* `noop`: the incoming state matched the current state, so no update was sent
* `ended`: returned by `DELETE /live-activity/stream/:stream_key`
# MCP Server
Source: https://activitysmith.com/docs/mcp-server
Connect Claude Code, Cursor, Codex, or any MCP client to ActivitySmith so AI agents can send Push Notifications and update Live Activities on your iPhone.
## Server URL
```bash theme={null}
https://mcp.activitysmith.com/mcp
```
## What Agents Can Do
Send Push Notifications to your paired devices or targeted channels.
Start, update, and end Live Activities on your iPhone, like live task progress on your Lock Screen.
Create widget metrics and update metric values for your Lock Screen Widgets.
List the history of your Push Notifications and Live Activities. List account users and devices, manage channels,
and API keys.
## Setup Instructions
The server URL is the same in every client. Approve the OAuth screen in your browser once, and the ActivitySmith tools become available in new sessions.
### Claude Code
```bash theme={null}
claude mcp add --transport http activitysmith https://mcp.activitysmith.com/mcp
```
Then run `/mcp` inside a Claude Code session to go through the authentication flow.
### Cursor
[Install in Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=activitysmith\&config=eyJ1cmwiOiJodHRwczovL21jcC5hY3Rpdml0eXNtaXRoLmNvbS9tY3AifQ==) with one click.
If you prefer manual setup, add the server to `~/.cursor/mcp.json`:
```json theme={null}
{
"mcpServers": {
"activitysmith": {
"url": "https://mcp.activitysmith.com/mcp"
}
}
}
```
Cursor prompts you to log in the first time the server is used.
### Codex
```bash theme={null}
codex mcp add activitysmith --url https://mcp.activitysmith.com/mcp
```
Then authenticate:
```bash theme={null}
codex mcp login activitysmith
```
### Other MCP Clients
For any client that asks for a remote MCP server URL, use:
```bash theme={null}
https://mcp.activitysmith.com/mcp
```
The authorization flow happens in ActivitySmith. After approval, tools run against the account you authorized.
## OAuth
ActivitySmith MCP uses OAuth. You do not need to create or paste an ActivitySmith API key into an agent prompt.
During authorization, ActivitySmith shows the access requested by the client. Most clients request read and write access so the agent can inspect current state and then take action when you ask it to.
## Example Prompts
```txt theme={null}
Notify me on my iPhone when this is done.
```
```txt theme={null}
Show me the progress visible on my Lock Screen with a Live Activity.
```
```txt theme={null}
Send me a Push Notification if this task gets blocked.
```
## Tools
The server exposes the following MCP tools, grouped by resource. Keep tool confirmation enabled in your client when possible, especially when you connect multiple MCP servers to the same agent session.
| Resource | Tool | Description |
| ------------------- | ----------------------------- | ------------------------------------------------------------------------------ |
| Push Notifications | `send_push_notification` | Send a Push Notification, with optional actions, media, and channel targeting. |
| Push Notifications | `list_push_notifications` | List Push Notification history for the account. |
| Push Notifications | `get_push_notification` | Get one Push Notification by public ID. |
| Live Activities | `set_live_activity_stream` | Start or update a managed Live Activity stream. |
| Live Activities | `pause_live_activity_stream` | Pause a stream and end its current Live Activity. |
| Live Activities | `resume_live_activity_stream` | Resume a paused stream so updates apply again. |
| Live Activities | `end_live_activity_stream` | End the current Live Activity and remove the stream key. |
| Live Activities | `list_live_activities` | List Live Activities for the account. |
| Lock Screen Widgets | `create_widget_metric` | Create a widget metric definition. |
| Lock Screen Widgets | `set_widget_metric_value` | Set the latest value for a widget metric. |
| Lock Screen Widgets | `update_widget_metric` | Update a widget metric definition. |
| Lock Screen Widgets | `list_widget_metrics` | List widget metrics for the account. |
| Lock Screen Widgets | `delete_widget_metric` | Delete a widget metric. |
| Channels | `create_channel` | Create a channel for targeting Push Notifications and Live Activities. |
| Channels | `get_channel` | Get one channel with its assigned users and devices. |
| Channels | `list_channels` | List channels for the account. |
| Channels | `update_channel` | Update a channel slug. |
| Channels | `set_channel_users` | Replace the user membership for a channel. |
| Channels | `set_channel_devices` | Replace explicit device assignments for a channel. |
| Channels | `delete_channel` | Delete a channel. |
| Users and Devices | `list_account_users` | List users in the account for channel assignment. |
| Users and Devices | `list_account_devices` | List active devices for explicit channel assignment. |
| API Keys | `create_api_key` | Create an API key. The key secret is shown once. |
| API Keys | `list_api_keys` | List API keys. Secret values are never returned. |
| API Keys | `update_api_key` | Update the name or channel scope of an API key. |
| API Keys | `delete_api_key` | Delete an API key by public ID. |
## Related
* [Push Notifications](/docs/api-reference/endpoint/push-notification)
* [Live Activity Streams](/docs/api-reference/endpoint/live-activity-stream)
* [Channels](/docs/channels)
* [Rate Limits](/docs/rate-limits)
# Rate Limits
Source: https://activitysmith.com/docs/rate-limits
Rate limits for API requests
## Concurrent Live Activities Limits
Concurrent Live Activities represent how many live activities ActivitySmith can process for you at the same time.
Number of concurrent live activities is limited to 4. This limit mimics the number of concurrent live activities that can be processed by the iOS. If you exceed this limit, additional live activities will be ignored until resources become available.
In the future, we will allow you to increase this limit by upgrading to a paid plan.
If you require higher concurrency limits, please contact us at [adam@activitysmith.com](mailto:adam@activitysmith.com).
## API Rate Limits
Rate limits are measured in requests per minute and are primarily in place to prevent abuse. When configured correctly, your real bottleneck will be concurrent live activities.
**Shared account limit**: 60 requests per minute across these endpoints:
* `POST /push-notification`
* `PUT /live-activity/stream/{stream_key}`
* `DELETE /live-activity/stream/{stream_key}`
* `POST /metrics/{metric_key}/value`
These rate limits are enforced to ensure fair usage and availability of the API for all users. If you require higher limits, please contact us at [adam@activitysmith.com](mailto:adam@activitysmith.com).
# CLI
Source: https://activitysmith.com/docs/sdks/cli
Use the ActivitySmith CLI to send push notifications, run specific iPhone Shortcuts from notification taps or actions, update widgets, and manage Live Activities from shell scripts, CI pipelines, coding agents, and terminal workflows.
## Installation
Install the ActivitySmith CLI globally with npm:
```bash CLI theme={null}
# Install globally with npm
npm install -g activitysmith-cli
```
## Agent Skill
Install the ActivitySmith skill when you want Codex, Claude, Cursor, or another skills-compatible agent to decide which ActivitySmith CLI command to run.
```bash CLI theme={null}
npx -y skills@latest add ActivitySmithHQ/activitysmith-cli --skill activitysmith
```
Use the skill when an agent should notify you with push notifications, include a notification tap or action that can open a URL or run a specific iPhone Shortcut, or keep task progress visible with Live Activities.
For example, a Codex agent can work on your computer, send a push notification when it needs your attention, and include a Shortcut action that runs an `OpenChatGPT` Shortcut on your iPhone so you can continue the conversation in the ChatGPT app.
## Usage
1. [Create an API key](https://activitysmith.com/app/keys)
2. Authenticate with `ACTIVITYSMITH_API_KEY` or pass `--api-key` per command.
3. Run `activitysmith --help` to inspect available commands.
Use the environment variable when you want the cleanest shell scripts:
```bash CLI theme={null}
export ACTIVITYSMITH_API_KEY="YOUR-API-KEY"
activitysmith --help
```
Or pass the key directly:
```bash CLI theme={null}
activitysmith --api-key "YOUR-API-KEY" push --title "Hello"
```
## Commands
### Push Notification
Use `activitysmith push` when a deploy fails, a CI run finishes, or a background job needs attention.
```bash CLI theme={null}
activitysmith push \
--title "Build Failed 🚨" \
--message "CI pipeline failed on main branch" \
--subtitle "main"
```
### Rich Push Notifications with Media
```bash CLI theme={null}
activitysmith push \
--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
`--media` can be combined with `--redirection`, but not with `--actions`. `--redirection` can be an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL.
### Actionable Push Notifications
Push notification redirection can open an HTTPS URL or run a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL when someone taps the notification. For expanded notification actions, `open_url` supports HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs. Webhooks are executed by the ActivitySmith backend and must use HTTPS.
```bash CLI theme={null}
activitysmith push \
--title "Build Failed 🚨" \
--message "CI pipeline failed on main branch" \
--redirection "https://github.com/org/repo/actions/runs/123456789" \
--actions '[
{
"title": "Open Build",
"type": "open_url",
"url": "https://github.com/org/repo/actions/runs/123456789"
},
{
"title": "Chat with Jarvis",
"type": "open_url",
"url": "shortcuts://run-shortcut?name=Jarvis"
},
{
"title": "Create Incident",
"type": "webhook",
"url": "https://hooks.example.com/incidents/create",
"method": "POST",
"body": {
"service": "payments-api",
"severity": "high",
"source": "activitysmith-cli"
}
}
]'
```
You can also load actions from a file:
```bash CLI theme={null}
activitysmith push \
--title "Build Failed 🚨" \
--message "CI pipeline failed on main branch" \
--actions-file "./actions.json"
```
## Live Activities
There are six 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 glance
* `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate
* `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs
* `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads
* `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
* `timer`: use it when you need countdowns or timers
### Start & Update Live Activity
Use a stable `stream_key` to identify the metric, job, deployment, or system you want to keep visible. The first `activity stream` command starts the Live Activity. Later commands with the same `stream_key` update it.
#### Stats
```bash CLI theme={null}
activitysmith activity stream sales-hourly \
--content-state '{
"title": "Sales",
"subtitle": "last hour",
"type": "stats",
"metrics": [
{ "label": "Revenue", "value": "$2430", "color": "blue" },
{ "label": "Orders", "value": "37", "color": "green" },
{ "label": "Conversion", "value": "4.8%", "color": "magenta" },
{ "label": "Avg Order", "value": "$65.68", "color": "yellow" },
{ "label": "Refunds", "value": "$84", "color": "red" },
{ "label": "New Buyers", "value": "18", "color": "cyan" }
]
}'
```
#### Metrics
```bash CLI theme={null}
activitysmith activity stream prod-web-1 \
--content-state '{
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"metrics": [
{ "label": "CPU", "value": 9, "unit": "%" },
{ "label": "MEM", "value": 45, "unit": "%" }
]
}'
```
#### Segmented Progress
```bash CLI theme={null}
activitysmith activity stream nightly-backup \
--content-state '{
"title": "Nightly Backup",
"subtitle": "upload archive",
"type": "segmented_progress",
"numberOfSteps": 3,
"currentStep": 2
}'
```
#### Progress
```bash CLI theme={null}
activitysmith activity stream search-reindex \
--content-state '{
"title": "Search Reindex",
"subtitle": "catalog-v2",
"type": "progress",
"percentage": 42
}'
```
#### Alert
```bash CLI theme={null}
activitysmith activity stream customer-ops \
--content-state '{
"title": "Reactivation",
"message": "Lumen came back after 2 weeks",
"type": "alert",
"icon": {
"symbol": "cloud.sun",
"color": "yellow"
},
"badge": {
"title": "Customer",
"color": "magenta"
}
}'
```
#### Timer
```bash CLI theme={null}
activitysmith activity stream benchmark-run \
--content-state '{
"title": "Benchmark Run",
"subtitle": "sampling",
"type": "timer",
"duration_seconds": 300,
"color": "cyan"
}'
```
For a countdown, send `duration_seconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `duration_seconds` out unless you want to change the timer.
To start at 00:00 and count up, set `counts_down` to `false` and leave out `duration_seconds`.
### End Live Activity
Call `activity 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 `autoDismissMinutes` to choose a different dismissal time, including `0` for immediate dismissal.
```bash CLI theme={null}
activitysmith activity end-stream prod-web-1 \
--content-state '{
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"metrics": [
{ "label": "CPU", "value": 7, "unit": "%" },
{ "label": "MEM", "value": 38, "unit": "%" }
],
"autoDismissMinutes": 2
}'
```
### Icons and Badges
Add more context to Live Activities with icons and badges.
#### Icon
Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.
```bash theme={null}
activitysmith activity stream prod-web-1 \
--content-state '{
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"icon": { "symbol": "server.rack", "color": "blue" },
"metrics": [
{ "label": "CPU", "value": 18, "unit": "%" },
{ "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](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
* [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app
* [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
#### Badge
Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities.
```bash theme={null}
activitysmith activity stream nightly-database-backup \
--content-state '{
"title": "Nightly Database Backup",
"subtitle": "verify restore",
"type": "progress",
"badge": { "title": "S3", "color": "cyan" },
"percentage": 62
}'
```
### Live Activity Colors
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`
### Live Activity Action
Live Activities can include an action button.
* `open_url`: open an HTTPS URL.
* `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app.
* `webhook`: trigger a backend GET/POST workflow.
#### Open URL action
```bash CLI theme={null}
activitysmith activity stream prod-web-1 \
--content-state '{
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"metrics": [
{ "label": "CPU", "value": 76, "unit": "%" },
{ "label": "MEM", "value": 52, "unit": "%" }
]
}' \
--action '{
"title": "Dashboard",
"type": "open_url",
"url": "https://status.example.com/servers/prod-web-1"
}'
```
#### Apple Shortcut action
```bash CLI theme={null}
activitysmith activity stream prod-web-1 \
--content-state '{
"title": "Server Health",
"subtitle": "prod-web-1",
"type": "metrics",
"metrics": [
{ "label": "CPU", "value": 76, "unit": "%" },
{ "label": "MEM", "value": 52, "unit": "%" }
]
}' \
--action '{
"title": "Chat with Jarvis",
"type": "open_url",
"url": "shortcuts://run-shortcut?name=Jarvis"
}'
```
#### Webhook action
```bash CLI theme={null}
activitysmith activity stream search-reindex \
--content-state '{
"title": "Reindexing product search",
"subtitle": "Shard 7 of 12",
"type": "segmented_progress",
"numberOfSteps": 12,
"currentStep": 7
}' \
--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-cli"
}
}'
```
#### Secondary action

Use `--secondary-action` when you want a second button beside the primary `--action`.
The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes.
```bash CLI theme={null}
activitysmith activity stream agent-approval \
--content-state '{
"title": "Approval Needed",
"message": "Should I send the follow-up email to Brightlane?",
"type": "alert",
"color": "green",
"icon": { "symbol": "sparkles", "color": "green" },
"badge": { "title": "Agent", "color": "green" }
}' \
--action '{
"title": "Send",
"type": "webhook",
"url": "https://agent.example.com/live-activity/approve",
"method": "POST",
"body": {
"approval_id": "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
"decision": "send"
}
}' \
--secondary-action '{
"title": "Deny",
"type": "webhook",
"url": "https://agent.example.com/live-activity/deny",
"method": "POST",
"body": {
"approval_id": "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
"decision": "deny"
}
}'
```
## Channels
Use `--channels` to target specific channels for `push` and `activity stream`.
```bash CLI theme={null}
activitysmith push \
--title "Build Failed 🚨" \
--message "CI pipeline failed on main branch" \
--channels "devs,ops"
```
```bash CLI theme={null}
activitysmith activity stream nightly-backup \
--content-state '{
"title": "Nightly database backup",
"type": "segmented_progress",
"numberOfSteps": 4,
"currentStep": 1
}' \
--channels "devs,ops"
```
## Widgets
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.
Use the metric key to update its value.
```bash theme={null}
activitysmith metrics update deploy.success_rate 99.9
```
String metric values work too.
```bash theme={null}
activitysmith metrics update prod.status healthy
```
## Output
Use `--json` for machine-readable output:
```bash CLI theme={null}
activitysmith push --title "Hello" --json
```
## Error Handling
The CLI exits non-zero on non-2xx responses and prints the API error body. That includes validation failures, rate limits, and Live Activity limit errors.
## Additional Resources
Install the ActivitySmith CLI from npm
View the CLI source on GitHub
# Go
Source: https://activitysmith.com/docs/sdks/go
Use the ActivitySmith Go SDK to send push notifications and Live Activity progress updates from Go services, workers, and automation jobs.
## Installation
Install the ActivitySmith Go SDK with `go get`:
```go Go theme={null}
go get github.com/ActivitySmithHQ/activitysmith-go
```
## Usage
1. [Create an API key](https://activitysmith.com/app/keys)
2. Pass the API key into `activitysmithsdk.New`.
3. Reuse the client anywhere you send pushes or Live Activity updates.
Create the client once:
```go Go theme={null}
package main
import (
"log"
activitysmithsdk "github.com/ActivitySmithHQ/activitysmith-go"
)
func main() {
activitysmith, err := activitysmithsdk.New("YOUR-API-KEY")
if err != nil {
log.Fatal(err)
}
}
```
### Send a Push Notification
Use `activitysmith.Notifications.Send` when a deploy finishes, a customer upgrades, or a background job needs attention.
```go Go theme={null}
input := activitysmithsdk.PushNotificationInput{
Title: "New subscription 💸",
Message: "Customer upgraded to Pro plan",
}
_, err := activitysmith.Notifications.
Send(input)
if err != nil {
log.Fatal(err)
}
```
### Rich Push Notifications with Media
```go Go theme={null}
input := activitysmithsdk.PushNotificationInput{
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",
}
_, err := activitysmith.Notifications.
Send(input)
if err != nil {
log.Fatal(err)
}
```
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
`Media` can be combined with `Redirection`, but not with `Actions`. `Redirection` can be an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL.
### Actionable Push Notifications
Push notification redirection can open an HTTPS URL or run a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL when someone taps the notification. For expanded notification actions, `open_url` supports HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs. Webhooks are executed by the ActivitySmith backend and must use HTTPS.
```go Go theme={null}
import (
"log"
activitysmithsdk "github.com/ActivitySmithHQ/activitysmith-go"
)
input := activitysmithsdk.PushNotificationInput{
Title: "New subscription 💸",
Message: "Customer upgraded to Pro plan",
Redirection: "https://crm.example.com/customers/cus_9f3a1d",
Actions: []activitysmithsdk.PushNotificationAction{
activitysmithsdk.PushAction(
"Open CRM",
"open_url",
"https://crm.example.com/customers/cus_9f3a1d",
),
activitysmithsdk.PushAction(
"Chat with Jarvis",
"open_url",
"shortcuts://run-shortcut?name=Jarvis",
),
activitysmithsdk.PushAction(
"Start Onboarding Workflow",
"webhook",
"https://hooks.example.com/activitysmith/onboarding/start",
activitysmithsdk.PushActionMethod("POST"),
activitysmithsdk.PushActionBody(map[string]interface{}{
"customer_id": "cus_9f3a1d",
"plan": "pro",
}),
),
},
}
_, err := activitysmith.Notifications.
Send(input)
if err != nil {
log.Fatal(err)
}
```
## Live Activities
There are six 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 glance
* `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate
* `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs
* `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads
* `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
* `timer`: use it when you need countdowns or timers
### Start & Update Live Activity
Use a stable `streamKey` 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 `streamKey` update it.
#### Stats
```go theme={null}
activitysmith.LiveActivities.Stream(
"sales-hourly",
activitysmithsdk.LiveActivityStreamInput{
Title: "Sales",
Subtitle: "last hour",
Type: "stats",
Metrics: []activitysmithsdk.ActivityMetric{
activitysmithsdk.Metric("Revenue", "$2430", activitysmithsdk.MetricColor("blue")),
activitysmithsdk.Metric("Orders", "37", activitysmithsdk.MetricColor("green")),
activitysmithsdk.Metric("Conversion", "4.8%", activitysmithsdk.MetricColor("magenta")),
activitysmithsdk.Metric("Avg Order", "$65.68", activitysmithsdk.MetricColor("yellow")),
activitysmithsdk.Metric("Refunds", "$84", activitysmithsdk.MetricColor("red")),
activitysmithsdk.Metric("New Buyers", "18", activitysmithsdk.MetricColor("cyan")),
},
},
)
```
#### Metrics
```go theme={null}
activitysmith.LiveActivities.Stream(
"prod-web-1",
activitysmithsdk.LiveActivityStreamInput{
Title: "Server Health",
Subtitle: "prod-web-1",
Type: "metrics",
Metrics: []activitysmithsdk.ActivityMetric{
activitysmithsdk.Metric("CPU", 9, activitysmithsdk.MetricUnit("%")),
activitysmithsdk.Metric("MEM", 45, activitysmithsdk.MetricUnit("%")),
},
},
)
```
#### Segmented Progress
```go theme={null}
activitysmith.LiveActivities.Stream(
"nightly-backup",
activitysmithsdk.LiveActivityStreamInput{
Title: "Nightly Backup",
Subtitle: "upload archive",
Type: "segmented_progress",
NumberOfSteps: 3,
CurrentStep: 2,
},
)
```
#### Progress
```go theme={null}
activitysmith.LiveActivities.Stream(
"search-reindex",
activitysmithsdk.LiveActivityStreamInput{
Title: "Search Reindex",
Subtitle: "catalog-v2",
Type: "progress",
Percentage: 42,
},
)
```
#### Alert
```go theme={null}
activitysmith.LiveActivities.Stream(
"customer-ops",
activitysmithsdk.LiveActivityStreamInput{
Title: "Reactivation",
Message: "Lumen came back after 2 weeks",
Type: activitysmithsdk.LiveActivityTypeAlert,
Icon: activitysmithsdk.AlertIcon("cloud.sun", "yellow"),
Badge: activitysmithsdk.AlertBadge("Customer", "magenta"),
},
)
```
#### Timer
```go theme={null}
activitysmith.LiveActivities.Stream(
"benchmark-run",
activitysmithsdk.LiveActivityStreamInput{
Title: "Benchmark Run",
Subtitle: "sampling",
Type: "timer",
DurationSeconds: 300,
Color: "cyan",
},
)
```
For a countdown, send `DurationSeconds`. You can update `Title`, `Subtitle`, `Color`, or any other visible field as the work changes. Leave `DurationSeconds` out unless you want to change the timer.
To start at 00:00 and count up, set `CountsDown` to `false` and leave out `DurationSeconds`.
### End Live Activity
Call `EndStream(...)` with the same `streamKey` 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 `AutoDismissMinutes` to choose a different dismissal time, including `0` for immediate dismissal.
```go theme={null}
activitysmith.LiveActivities.EndStream(
"prod-web-1",
activitysmithsdk.LiveActivityStreamEndInput{
Title: "Server Health",
Subtitle: "prod-web-1",
Type: "metrics",
Metrics: []activitysmithsdk.ActivityMetric{
activitysmithsdk.Metric("CPU", 7, activitysmithsdk.MetricUnit("%")),
activitysmithsdk.Metric("MEM", 38, activitysmithsdk.MetricUnit("%")),
},
AutoDismissMinutes: 2,
},
)
```
### Icons and Badges
Add more context to Live Activities with icons and badges.
#### Icon
Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.
```go theme={null}
activitysmith.LiveActivities.Stream(
"prod-web-1",
activitysmithsdk.LiveActivityStreamInput{
Title: "Server Health",
Subtitle: "prod-web-1",
Type: "metrics",
Icon: activitysmithsdk.AlertIcon("server.rack", "blue"),
Metrics: []activitysmithsdk.ActivityMetric{
activitysmithsdk.Metric("CPU", 18, activitysmithsdk.MetricUnit("%")),
activitysmithsdk.Metric("MEM", 42, activitysmithsdk.MetricUnit("%")),
},
},
)
```
The `Icon` symbol value is an Apple SF Symbol name. Browse the catalog with one of these tools:
* [ActivitySmith app](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
* [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app
* [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
#### Badge
Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities.
```go theme={null}
activitysmith.LiveActivities.Stream(
"nightly-database-backup",
activitysmithsdk.LiveActivityStreamInput{
Title: "Nightly Database Backup",
Subtitle: "verify restore",
Type: "progress",
Badge: activitysmithsdk.AlertBadge("S3", "cyan"),
Percentage: 62,
},
)
```
### Live Activity Colors
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`
### Live Activity Action
Live Activities can include an action button.
* `open_url`: open an HTTPS URL.
* `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app.
* `webhook`: trigger a backend GET/POST workflow.
#### Open URL action
```go theme={null}
activitysmith.LiveActivities.Stream(
"prod-web-1",
activitysmithsdk.LiveActivityStreamInput{
Title: "Server Health",
Subtitle: "prod-web-1",
Type: "metrics",
Metrics: []activitysmithsdk.ActivityMetric{
activitysmithsdk.Metric("CPU", 76, activitysmithsdk.MetricUnit("%")),
activitysmithsdk.Metric("MEM", 52, activitysmithsdk.MetricUnit("%")),
},
Action: &activitysmithsdk.LiveActivityActionInput{
Title: "Dashboard",
Type: "open_url",
URL: "https://status.example.com/servers/prod-web-1",
},
},
)
```
#### Apple Shortcut action
```go theme={null}
activitysmith.LiveActivities.Stream(
"prod-web-1",
activitysmithsdk.LiveActivityStreamInput{
Title: "Server Health",
Subtitle: "prod-web-1",
Type: "metrics",
Metrics: []activitysmithsdk.ActivityMetric{
activitysmithsdk.Metric("CPU", 76, activitysmithsdk.MetricUnit("%")),
activitysmithsdk.Metric("MEM", 52, activitysmithsdk.MetricUnit("%")),
},
Action: &activitysmithsdk.LiveActivityActionInput{
Title: "Chat with Jarvis",
Type: "open_url",
URL: "shortcuts://run-shortcut?name=Jarvis",
},
},
)
```
#### Webhook action
```go theme={null}
activitysmith.LiveActivities.Stream(
"search-reindex",
activitysmithsdk.LiveActivityStreamInput{
Title: "Reindexing product search",
Subtitle: "Shard 7 of 12",
Type: "segmented_progress",
NumberOfSteps: 12,
CurrentStep: 7,
Action: &activitysmithsdk.LiveActivityActionInput{
Title: "Pause Reindex",
Type: "webhook",
URL: "https://ops.example.com/hooks/search/reindex/pause",
Method: "POST",
Body: map[string]interface{}{
"job_id": "reindex-2026-03-19",
"requested_by": "activitysmith-go",
},
},
},
)
```
#### Secondary action

Use `secondary_action` when you want a second button beside the primary `action`.
The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes.
```go theme={null}
activitysmith.LiveActivities.Stream(
"agent-approval",
activitysmithsdk.LiveActivityStreamInput{
Title: "Approval Needed",
Message: "Should I send the follow-up email to Brightlane?",
Type: "alert",
Color: "green",
Icon: activitysmithsdk.AlertIcon("sparkles", "green"),
Badge: activitysmithsdk.AlertBadge("Agent", "green"),
Action: &activitysmithsdk.LiveActivityActionInput{
Title: "Send",
Type: "webhook",
URL: "https://agent.example.com/live-activity/approve",
Method: "POST",
Body: map[string]interface{}{
"approval_id": "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
"decision": "send",
},
},
SecondaryAction: &activitysmithsdk.LiveActivityActionInput{
Title: "Deny",
Type: "webhook",
URL: "https://agent.example.com/live-activity/deny",
Method: "POST",
Body: map[string]interface{}{
"approval_id": "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
"decision": "deny",
},
},
},
)
```
## Channels
Target specific channels when sending a push notification or streaming a Live Activity.
```go Go theme={null}
activitysmith.Notifications.Send(activitysmithsdk.PushNotificationInput{
Title: "New subscription 💸",
Message: "Customer upgraded to Pro plan",
Channels: []string{"ios-builds", "engineering"},
})
activitysmith.LiveActivities.Stream(
"nightly-backup",
activitysmithsdk.LiveActivityStreamInput{
Title: "Nightly database backup",
NumberOfSteps: 3,
CurrentStep: 1,
Type: "segmented_progress",
Channels: []string{"ios-builds"},
},
)
```
## Widgets
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.
Use the metric key to update its value.
```go theme={null}
_, err := activitysmith.Metrics.Update("deploy.success_rate", 99.9)
if err != nil {
log.Fatal(err)
}
```
String metric values work too.
```go theme={null}
_, err = activitysmith.Metrics.Update("prod.status", "healthy")
if err != nil {
log.Fatal(err)
}
```
## Error Handling
SDK calls return `response, err`, so check `err` after every call.
## Additional Resources
View the Go SDK source on GitHub
# Node.js
Source: https://activitysmith.com/docs/sdks/node
Use the ActivitySmith Node.js SDK to send push notifications and Live Activity progress updates from Node services, jobs, and CI workflows.
## Installation
Install the ActivitySmith Node.js SDK with npm:
```js Node theme={null}
npm install activitysmith
```
## Usage
1. [Create an API key](https://activitysmith.com/app/keys)
2. Set `ACTIVITYSMITH_API_KEY` or pass `apiKey` when creating the client.
3. Reuse the client anywhere you send pushes or Live Activity updates.
Create the client once:
```js Node theme={null}
import ActivitySmith from "activitysmith";
const activitysmith = new ActivitySmith({
apiKey: process.env.ACTIVITYSMITH_API_KEY,
});
```
### Send a Push Notification
Use `activitysmith.notifications.send` when a deploy finishes, a customer upgrades, or a background job needs attention. `title` is required. `message` and `subtitle` are optional.
```js Node theme={null}
await activitysmith.notifications.send({
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
});
```
### Rich Push Notifications with Media
```js Node theme={null}
await 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
`media` can be combined with `redirection`, but not with `actions`. `redirection` can be an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL.
### Actionable Push Notifications
Push notification redirection can open an HTTPS URL or run a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL when someone taps the notification. For expanded notification actions, `open_url` supports HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs. Webhooks are executed by the ActivitySmith backend and must use HTTPS.
```js Node theme={null}
await activitysmith.notifications.send({
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
redirection: "https://crm.example.com/customers/cus_9f3a1d",
actions: [
{
title: "Open CRM",
type: "open_url",
url: "https://crm.example.com/customers/cus_9f3a1d",
},
{
title: "Chat with Jarvis",
type: "open_url",
url: "shortcuts://run-shortcut?name=Jarvis",
},
{
title: "Start Onboarding Workflow",
type: "webhook",
url: "https://hooks.example.com/activitysmith/onboarding/start",
method: "POST",
body: {
customer_id: "cus_9f3a1d",
plan: "pro",
},
},
],
});
```
## Live Activities
There are six 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 glance
* `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate
* `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs
* `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads
* `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
* `timer`: use it when you need countdowns or timers
### Start & Update Live Activity
Use a stable `streamKey` 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 `streamKey` update it.
#### Stats
```ts theme={null}
await activitysmith.liveActivities.stream("sales-hourly", {
content_state: {
title: "Sales",
subtitle: "last hour",
type: "stats",
metrics: [
{ label: "Revenue", value: "$2430", color: "blue" },
{ label: "Orders", value: "37", color: "green" },
{ label: "Conversion", value: "4.8%", color: "magenta" },
{ label: "Avg Order", value: "$65.68", color: "yellow" },
{ label: "Refunds", value: "$84", color: "red" },
{ label: "New Buyers", value: "18", color: "cyan" },
],
},
});
```
#### Metrics
```ts theme={null}
await activitysmith.liveActivities.stream("prod-web-1", {
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 9, unit: "%" },
{ label: "MEM", value: 45, unit: "%" },
],
},
});
```
#### Segmented Progress
```ts theme={null}
await activitysmith.liveActivities.stream("nightly-backup", {
content_state: {
title: "Nightly Backup",
subtitle: "upload archive",
type: "segmented_progress",
number_of_steps: 3,
current_step: 2,
},
});
```
#### Progress
```ts theme={null}
await activitysmith.liveActivities.stream("search-reindex", {
content_state: {
title: "Search Reindex",
subtitle: "catalog-v2",
type: "progress",
percentage: 42,
},
});
```
#### Alert
```ts theme={null}
await activitysmith.liveActivities.stream("customer-ops", {
content_state: ActivitySmith.contentState({
title: "Reactivation",
message: "Lumen came back after 2 weeks",
type: "alert",
icon: ActivitySmith.alertIcon("cloud.sun", { color: "yellow" }),
badge: ActivitySmith.alertBadge("Customer", { color: "magenta" }),
}),
});
```
#### Timer
```ts theme={null}
await activitysmith.liveActivities.stream("benchmark-run", {
content_state: {
title: "Benchmark Run",
subtitle: "sampling",
type: "timer",
duration_seconds: 300,
color: "cyan",
},
});
```
For a countdown, send `duration_seconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `duration_seconds` out unless you want to change the timer.
To start at 00:00 and count up, set `counts_down: false` and leave out `duration_seconds`.
### End Live Activity
Call `endStream(...)` with the same `streamKey` 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.
```ts theme={null}
await activitysmith.liveActivities.endStream("prod-web-1", {
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 7, unit: "%" },
{ label: "MEM", value: 38, unit: "%" },
],
auto_dismiss_minutes: 2,
},
});
```
### Icons and Badges
Add more context to Live Activities with icons and badges.
#### Icon
Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.
```ts theme={null}
await activitysmith.liveActivities.stream("prod-web-1", {
content_state: ActivitySmith.contentState({
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
icon: ActivitySmith.alertIcon("server.rack", { color: "blue" }),
metrics: [
{ label: "CPU", value: 18, unit: "%" },
{ 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](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
* [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app
* [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
#### Badge
Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities.
```ts theme={null}
await activitysmith.liveActivities.stream("nightly-database-backup", {
content_state: ActivitySmith.contentState({
title: "Nightly Database Backup",
subtitle: "verify restore",
type: "progress",
badge: ActivitySmith.alertBadge("S3", { color: "cyan" }),
percentage: 62,
}),
});
```
### Live Activity Colors
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`
### Live Activity Action
Live Activities can include an action button.
* `open_url`: open an HTTPS URL.
* `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app.
* `webhook`: trigger a backend GET/POST workflow.
#### Open URL action
```ts theme={null}
await activitysmith.liveActivities.stream("prod-web-1", {
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 76, unit: "%" },
{ label: "MEM", value: 52, unit: "%" },
],
},
action: {
title: "Dashboard",
type: "open_url",
url: "https://status.example.com/servers/prod-web-1",
},
});
```
#### Apple Shortcut action
```ts theme={null}
await activitysmith.liveActivities.stream("prod-web-1", {
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 76, unit: "%" },
{ label: "MEM", value: 52, unit: "%" },
],
},
action: {
title: "Chat with Jarvis",
type: "open_url",
url: "shortcuts://run-shortcut?name=Jarvis",
},
});
```
#### Webhook action
```ts theme={null}
await activitysmith.liveActivities.stream("search-reindex", {
content_state: {
title: "Reindexing product search",
subtitle: "Shard 7 of 12",
type: "segmented_progress",
number_of_steps: 12,
current_step: 7,
},
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-node",
},
},
});
```
#### Secondary action

Use `secondary_action` when you want a second button beside the primary `action`.
The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes.
```ts theme={null}
await activitysmith.liveActivities.stream("agent-approval", {
content_state: {
title: "Approval Needed",
message: "Should I send the follow-up email to Brightlane?",
type: "alert",
color: "green",
icon: {
symbol: "sparkles",
color: "green",
},
badge: {
title: "Agent",
color: "green",
},
},
action: {
title: "Send",
type: "webhook",
url: "https://agent.example.com/live-activity/approve",
method: "POST",
body: {
approval_id: "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
decision: "send",
},
},
secondary_action: {
title: "Deny",
type: "webhook",
url: "https://agent.example.com/live-activity/deny",
method: "POST",
body: {
approval_id: "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
decision: "deny",
},
},
});
```
## Channels
Target specific channels when sending a push notification or streaming a Live Activity.
```js Node theme={null}
await activitysmith.notifications.send({
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
channels: ["ios-builds", "engineering"],
});
await activitysmith.liveActivities.stream("nightly-backup", {
channels: ["ios-builds"],
content_state: {
title: "Nightly database backup",
number_of_steps: 3,
current_step: 1,
type: "segmented_progress",
},
});
```
## Widgets
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.
Use the metric key to update its value.
```ts theme={null}
await activitysmith.metrics.update("deploy.success_rate", 99.9);
```
String metric values work too.
```ts theme={null}
await activitysmith.metrics.update("prod.status", "healthy");
```
## Error Handling
SDK calls return promises, so wrap API calls with `try/catch`:
```js Node theme={null}
try {
await activitysmith.notifications.send({ title: "Hello" });
} catch (error) {
console.error(error);
}
```
## Additional Resources
Install the ActivitySmith Node.js SDK from npm
View the Node.js SDK source on GitHub
# Overview
Source: https://activitysmith.com/docs/sdks/overview
ActivitySmith SDKs and the CLI help you send push notifications, update widgets, and manage Live Activities on your iOS devices.
## Official SDKs
Explore the Node SDK for ActivitySmith.
Explore the Python SDK for ActivitySmith.
Explore the Go SDK for ActivitySmith.
Explore the PHP SDK for ActivitySmith.
Explore the Ruby SDK for ActivitySmith.
Use ActivitySmith directly from the command line.
# PHP
Source: https://activitysmith.com/docs/sdks/php
Use the ActivitySmith PHP SDK to send push notifications and Live Activity progress updates from PHP apps, queues, and scheduled jobs.
## Installation
Install the ActivitySmith PHP SDK with Composer:
```php PHP theme={null}
composer require activitysmith/activitysmith
```
## Usage
1. [Create an API key](https://activitysmith.com/app/keys)
2. Set `ACTIVITYSMITH_API_KEY` or pass it directly to `ActivitySmith`.
3. Reuse the client anywhere you send pushes or Live Activity updates.
Create the client once:
```php PHP theme={null}
notifications->send` when a deploy finishes, a customer upgrades, or a background job needs attention. `title` is required. `message` and `subtitle` are optional.
```php PHP theme={null}
$activitysmith->notifications->send(
title: 'New subscription 💸',
message: 'Customer upgraded to Pro plan',
);
```
### Rich Push Notifications with Media
```php PHP theme={null}
$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
`media` can be combined with `redirection`, but not with `actions`. `redirection` can be an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL.
### Actionable Push Notifications
Push notification redirection can open an HTTPS URL or run a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL when someone taps the notification. For expanded notification actions, `open_url` supports HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs. Webhooks are executed by the ActivitySmith backend and must use HTTPS.
```php PHP theme={null}
$activitysmith->notifications->send(
title: 'New subscription 💸',
message: 'Customer upgraded to Pro plan',
redirection: 'https://crm.example.com/customers/cus_9f3a1d',
actions: [
PushAction::make(
title: 'Open CRM',
type: 'open_url',
url: 'https://crm.example.com/customers/cus_9f3a1d',
),
PushAction::make(
title: 'Chat with Jarvis',
type: 'open_url',
url: 'shortcuts://run-shortcut?name=Jarvis',
),
PushAction::make(
title: 'Start Onboarding Workflow',
type: 'webhook',
url: 'https://hooks.example.com/activitysmith/onboarding/start',
method: 'POST',
body: [
'customer_id' => 'cus_9f3a1d',
'plan' => 'pro',
],
),
],
);
```
## Live Activities
There are six 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 glance
* `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate
* `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs
* `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads
* `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
* `timer`: use it when you need countdowns or timers
### Start & Update Live Activity
Use a stable `streamKey` 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 `streamKey` update it.
#### Stats
```php theme={null}
$activitysmith->liveActivities->stream(
'sales-hourly',
contentState: LiveActivityContentState::make(
title: 'Sales',
subtitle: 'last hour',
type: 'stats',
metrics: [
LiveActivityMetric::make(label: 'Revenue', value: '$2430', color: 'blue'),
LiveActivityMetric::make(label: 'Orders', value: '37', color: 'green'),
LiveActivityMetric::make(label: 'Conversion', value: '4.8%', color: 'magenta'),
LiveActivityMetric::make(label: 'Avg Order', value: '$65.68', color: 'yellow'),
LiveActivityMetric::make(label: 'Refunds', value: '$84', color: 'red'),
LiveActivityMetric::make(label: 'New Buyers', value: '18', color: 'cyan'),
],
),
);
```
#### Metrics
```php theme={null}
$activitysmith->liveActivities->stream(
'prod-web-1',
contentState: LiveActivityContentState::make(
title: 'Server Health',
subtitle: 'prod-web-1',
type: 'metrics',
metrics: [
LiveActivityMetric::make(label: 'CPU', value: 9, unit: '%'),
LiveActivityMetric::make(label: 'MEM', value: 45, unit: '%'),
],
),
);
```
#### Segmented Progress
```php theme={null}
$activitysmith->liveActivities->stream(
'nightly-backup',
contentState: LiveActivityContentState::make(
title: 'Nightly Backup',
subtitle: 'upload archive',
type: 'segmented_progress',
numberOfSteps: 3,
currentStep: 2,
),
);
```
#### Progress
```php theme={null}
$activitysmith->liveActivities->stream(
'search-reindex',
contentState: LiveActivityContentState::make(
title: 'Search Reindex',
subtitle: 'catalog-v2',
type: 'progress',
percentage: 42,
),
);
```
#### Alert
```php theme={null}
$activitysmith->liveActivities->stream(
'customer-ops',
contentState: LiveActivityContentState::make(
title: 'Reactivation',
message: 'Lumen came back after 2 weeks',
type: 'alert',
icon: LiveActivityAlertIcon::make(symbol: 'cloud.sun', color: 'yellow'),
badge: LiveActivityAlertBadge::make(title: 'Customer', color: 'magenta'),
),
);
```
#### Timer
```php theme={null}
$activitysmith->liveActivities->stream(
'benchmark-run',
contentState: LiveActivityContentState::make(
title: 'Benchmark Run',
subtitle: 'sampling',
type: 'timer',
durationSeconds: 300,
color: 'cyan',
),
);
```
For a countdown, send `durationSeconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `durationSeconds` out unless you want to change the timer.
To start at 00:00 and count up, set `countsDown` to `false` and leave out `durationSeconds`.
### End Live Activity
Call `endStream(...)` with the same `streamKey` 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 `autoDismissMinutes` to choose a different dismissal time, including `0` for immediate dismissal.
```php theme={null}
$activitysmith->liveActivities->endStream(
'prod-web-1',
contentState: LiveActivityContentState::make(
title: 'Server Health',
subtitle: 'prod-web-1',
type: 'metrics',
metrics: [
LiveActivityMetric::make(label: 'CPU', value: 7, unit: '%'),
LiveActivityMetric::make(label: 'MEM', value: 38, unit: '%'),
],
autoDismissMinutes: 2,
),
);
```
### Icons and Badges
Add more context to Live Activities with icons and badges.
#### Icon
Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.
```php theme={null}
$activitysmith->liveActivities->stream(
'prod-web-1',
contentState: LiveActivityContentState::make(
title: 'Server Health',
subtitle: 'prod-web-1',
type: LiveActivities::TYPE_METRICS,
icon: LiveActivityAlertIcon::make(symbol: 'server.rack', color: 'blue'),
metrics: [
LiveActivityMetric::make(label: 'CPU', value: 18, unit: '%'),
LiveActivityMetric::make(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](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
* [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app
* [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
#### Badge
Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities.
```php theme={null}
$activitysmith->liveActivities->stream(
'nightly-database-backup',
contentState: LiveActivityContentState::make(
title: 'Nightly Database Backup',
subtitle: 'verify restore',
type: LiveActivities::TYPE_PROGRESS,
badge: LiveActivityAlertBadge::make(title: 'S3', color: 'cyan'),
percentage: 62,
),
);
```
### Live Activity Colors
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`
### Live Activity Action
Live Activities can include an action button.
* `open_url`: open an HTTPS URL.
* `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app.
* `webhook`: trigger a backend GET/POST workflow.
#### Open URL action
```php theme={null}
$activitysmith->liveActivities->stream(
'prod-web-1',
contentState: LiveActivityContentState::make(
title: 'Server Health',
subtitle: 'prod-web-1',
type: 'metrics',
metrics: [
LiveActivityMetric::make(label: 'CPU', value: 76, unit: '%'),
LiveActivityMetric::make(label: 'MEM', value: 52, unit: '%'),
],
),
action: LiveActivityAction::make(
title: 'Dashboard',
type: 'open_url',
url: 'https://status.example.com/servers/prod-web-1',
),
);
```
#### Apple Shortcut action
```php theme={null}
$activitysmith->liveActivities->stream(
'prod-web-1',
contentState: LiveActivityContentState::make(
title: 'Server Health',
subtitle: 'prod-web-1',
type: 'metrics',
metrics: [
LiveActivityMetric::make(label: 'CPU', value: 76, unit: '%'),
LiveActivityMetric::make(label: 'MEM', value: 52, unit: '%'),
],
),
action: LiveActivityAction::make(
title: 'Chat with Jarvis',
type: 'open_url',
url: 'shortcuts://run-shortcut?name=Jarvis',
),
);
```
#### Webhook action
```php theme={null}
$activitysmith->liveActivities->stream(
'search-reindex',
contentState: LiveActivityContentState::make(
title: 'Reindexing product search',
subtitle: 'Shard 7 of 12',
type: 'segmented_progress',
numberOfSteps: 12,
currentStep: 7,
),
action: LiveActivityAction::make(
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-php',
],
),
);
```
#### Secondary action

Use `secondary_action` when you want a second button beside the primary `action`.
The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes.
```php theme={null}
$activitysmith->liveActivities->stream(
'agent-approval',
contentState: LiveActivityContentState::make(
title: 'Approval Needed',
message: 'Should I send the follow-up email to Brightlane?',
type: 'alert',
color: 'green',
icon: LiveActivityAlertIcon::make(symbol: 'sparkles', color: 'green'),
badge: LiveActivityAlertBadge::make(title: 'Agent', color: 'green'),
),
action: LiveActivityAction::make(
title: 'Send',
type: 'webhook',
url: 'https://agent.example.com/live-activity/approve',
method: 'POST',
body: [
'approval_id' => 'approval_01JY3J7Q9S0P8M1V5PZK7DR4M2',
'decision' => 'send',
],
),
secondaryAction: LiveActivityAction::make(
title: 'Deny',
type: 'webhook',
url: 'https://agent.example.com/live-activity/deny',
method: 'POST',
body: [
'approval_id' => 'approval_01JY3J7Q9S0P8M1V5PZK7DR4M2',
'decision' => 'deny',
],
),
);
```
## Channels
Target specific channels when sending a push notification or streaming a Live Activity.
```php PHP theme={null}
$activitysmith->notifications->send(
title: 'New subscription 💸',
message: 'Customer upgraded to Pro plan',
channels: ['ios-builds', 'engineering'],
);
$activitysmith->liveActivities->stream(
'nightly-backup',
contentState: LiveActivityContentState::make(
title: 'Nightly database backup',
type: 'segmented_progress',
numberOfSteps: 3,
currentStep: 1,
),
channels: ['ios-builds'],
);
```
## Widgets
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.
Use the metric key to update its value.
```php theme={null}
$activitysmith->metrics->update('deploy.success_rate', 99.9);
```
String metric values work too.
```php theme={null}
$activitysmith->metrics->update('prod.status', 'healthy');
```
## Error Handling
Wrap SDK calls with `try/catch`:
```php PHP theme={null}
try {
$activitysmith->notifications->send(title: 'Hello');
} catch (\Throwable $error) {
echo $error->getMessage();
}
```
## Additional Resources
Install the ActivitySmith PHP SDK from Packagist
View the PHP SDK source on GitHub
# Python
Source: https://activitysmith.com/docs/sdks/python
Use the ActivitySmith Python SDK to send push notifications and Live Activity progress updates from Python scripts, jobs, and backend services.
## Installation
Install the ActivitySmith Python SDK with pip:
```python Python theme={null}
pip install activitysmith
```
## Usage
1. [Create an API key](https://activitysmith.com/app/keys)
2. Set `ACTIVITYSMITH_API_KEY` or pass it directly to `ActivitySmith`.
3. Reuse the client anywhere you send pushes or Live Activity updates.
Create the client once:
```python Python theme={null}
import os
from activitysmith import (
ActivitySmith,
action,
alert_badge,
alert_icon,
content_state,
metric,
)
activitysmith = ActivitySmith(api_key=os.environ.get("ACTIVITYSMITH_API_KEY", "YOUR-API-KEY"))
```
### Send a Push Notification
Use `activitysmith.notifications.send` when a deploy finishes, a customer upgrades, or a background job needs attention. `title` is required. `message` and `subtitle` are optional.
```python Python theme={null}
activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
)
```
### Rich Push Notifications with Media
```python Python theme={null}
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
`media` can be combined with `redirection`, but not with `actions`. `redirection` can be an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL.
### Actionable Push Notifications
Push notification redirection can open an HTTPS URL or run a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL when someone taps the notification. For expanded notification actions, `open_url` supports HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs. Webhooks are executed by the ActivitySmith backend and must use HTTPS.
```python Python theme={null}
activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
redirection="https://crm.example.com/customers/cus_9f3a1d",
actions=[
action(
title="Open CRM",
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",
},
),
],
)
```
## Live Activities
There are six 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 glance
* `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate
* `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs
* `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads
* `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
* `timer`: use it when you need countdowns or timers
### Start & Update Live Activity
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.
#### Stats
```python theme={null}
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"),
],
),
)
```
#### Metrics
```python theme={null}
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="%"),
],
),
)
```
#### Segmented Progress
```python theme={null}
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,
),
)
```
#### Progress
```python theme={null}
activitysmith.live_activities.stream(
"search-reindex",
content_state=content_state(
title="Search Reindex",
subtitle="catalog-v2",
type="progress",
percentage=42,
),
)
```
#### Alert
```python theme={null}
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"),
),
)
```
#### Timer
```python theme={null}
activitysmith.live_activities.stream(
"benchmark-run",
content_state=content_state(
title="Benchmark Run",
subtitle="sampling",
type="timer",
duration_seconds=300,
color="cyan",
),
)
```
For a countdown, send `duration_seconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `duration_seconds` out unless you want to change the timer.
To start at 00:00 and count up, set `counts_down=False` and leave out `duration_seconds`.
### End Live Activity
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.
```python theme={null}
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,
),
)
```
### Icons and Badges
Add more context to Live Activities with icons and badges.
#### Icon
Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.
```python theme={null}
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](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
* [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app
* [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
#### Badge
Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities.
```python theme={null}
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,
),
)
```
### Live Activity Colors
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`
### Live Activity Action
Live Activities can include an action button.
* `open_url`: open an HTTPS URL.
* `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app.
* `webhook`: trigger a backend GET/POST workflow.
#### Open URL action
```python theme={null}
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://status.example.com/servers/prod-web-1",
),
)
```
#### Apple Shortcut action
```python theme={null}
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="Chat with Jarvis",
type="open_url",
url="shortcuts://run-shortcut?name=Jarvis",
),
)
```
#### Webhook action
```python theme={null}
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",
},
),
)
```
#### Secondary action

Use `secondary_action` when you want a second button beside the primary `action`.
The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes.
```python theme={null}
activitysmith.live_activities.stream(
"agent-approval",
content_state=content_state(
title="Approval Needed",
message="Should I send the follow-up email to Brightlane?",
type="alert",
color="green",
icon=alert_icon("sparkles", color="green"),
badge=alert_badge("Agent", color="green"),
),
action=action(
title="Send",
type="webhook",
url="https://agent.example.com/live-activity/approve",
method="POST",
body={
"approval_id": "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
"decision": "send",
},
),
secondary_action=action(
title="Deny",
type="webhook",
url="https://agent.example.com/live-activity/deny",
method="POST",
body={
"approval_id": "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
"decision": "deny",
},
),
)
```
## Channels
Target specific channels when sending a push notification or streaming a Live Activity.
```python Python theme={null}
activitysmith.notifications.send(
title="New subscription 💸",
message="Customer upgraded to Pro plan",
channels=["ios-builds", "engineering"],
)
activitysmith.live_activities.stream(
"nightly-backup",
content_state=content_state(
title="Nightly database backup",
type="segmented_progress",
number_of_steps=3,
current_step=1,
),
channels=["ios-builds"],
)
```
## Widgets
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.
Use the metric key to update its value.
```python theme={null}
activitysmith.metrics.update("deploy.success_rate", 99.9)
```
String metric values work too.
```python theme={null}
activitysmith.metrics.update("prod.status", "healthy")
```
## Error Handling
Wrap API calls with `try/except`. The SDK raises exceptions for non-2xx responses. Rate limit errors use the `error` and `message` fields, and Live Activity limit errors include `limit` and `active`. See [Rate Limits](/docs/rate-limits) for details.
## Additional Resources
Install the ActivitySmith Python SDK from PyPI
View the Python SDK source on GitHub
# Ruby
Source: https://activitysmith.com/docs/sdks/ruby
Use the ActivitySmith Ruby SDK to send push notifications and Live Activity progress updates from Ruby apps, workers, and scheduled jobs.
## Installation
Install the ActivitySmith Ruby SDK with RubyGems:
```ruby Ruby theme={null}
gem install activitysmith
```
## Usage
1. [Create an API key](https://activitysmith.com/app/keys)
2. Set `ACTIVITYSMITH_API_KEY` or pass it directly to `ActivitySmith::Client`.
3. Reuse the client anywhere you send pushes or Live Activity updates.
Create the client once:
```ruby Ruby theme={null}
require "activitysmith"
api_key = ENV["ACTIVITYSMITH_API_KEY"] || "YOUR-API-KEY"
activitysmith = ActivitySmith::Client.new(api_key: api_key)
```
### Send a Push Notification
Use `activitysmith.notifications.send` when a deploy finishes, a customer upgrades, or a background job needs attention. `title` is required. `message` and `subtitle` are optional.
```ruby Ruby theme={null}
activitysmith.notifications.send(
{
title: "New subscription 💸",
message: "Customer upgraded to Pro plan"
}
)
```
### Rich Push Notifications with Media
```ruby Ruby theme={null}
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
`media` can be combined with `redirection`, but not with `actions`. `redirection` can be an HTTPS URL or a `shortcuts://run-shortcut?name=...` URL.
### Actionable Push Notifications
Push notification redirection can open an HTTPS URL or run a specific iPhone Shortcut with a `shortcuts://run-shortcut?name=...` URL when someone taps the notification. For expanded notification actions, `open_url` supports HTTPS URLs and `shortcuts://run-shortcut?name=...` URLs. Webhooks are executed by the ActivitySmith backend and must use HTTPS.
```ruby Ruby theme={null}
activitysmith.notifications.send(
{
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
redirection: "https://crm.example.com/customers/cus_9f3a1d",
actions: [
{
title: "Open CRM",
type: "open_url",
url: "https://crm.example.com/customers/cus_9f3a1d"
},
{
title: "Chat with Jarvis",
type: "open_url",
url: "shortcuts://run-shortcut?name=Jarvis"
},
{
title: "Start Onboarding Workflow",
type: "webhook",
url: "https://hooks.example.com/activitysmith/onboarding/start",
method: "POST",
body: {
customer_id: "cus_9f3a1d",
plan: "pro"
}
}
]
}
)
```
## Live Activities
There are six 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 glance
* `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate
* `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs
* `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads
* `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states
* `timer`: use it when you need countdowns or timers
### Start & Update Live Activity
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.
#### Stats
```ruby theme={null}
activitysmith.live_activities.stream(
"sales-hourly",
{
content_state: {
title: "Sales",
subtitle: "last hour",
type: "stats",
metrics: [
{ label: "Revenue", value: "$2430", color: "blue" },
{ label: "Orders", value: "37", color: "green" },
{ label: "Conversion", value: "4.8%", color: "magenta" },
{ label: "Avg Order", value: "$65.68", color: "yellow" },
{ label: "Refunds", value: "$84", color: "red" },
{ label: "New Buyers", value: "18", color: "cyan" }
]
}
}
)
```
#### Metrics
```ruby theme={null}
activitysmith.live_activities.stream(
"prod-web-1",
{
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 9, unit: "%" },
{ label: "MEM", value: 45, unit: "%" }
]
}
}
)
```
#### Segmented Progress
```ruby theme={null}
activitysmith.live_activities.stream(
"nightly-backup",
{
content_state: {
title: "Nightly Backup",
subtitle: "upload archive",
type: "segmented_progress",
number_of_steps: 3,
current_step: 2
}
}
)
```
#### Progress
```ruby theme={null}
activitysmith.live_activities.stream(
"search-reindex",
{
content_state: {
title: "Search Reindex",
subtitle: "catalog-v2",
type: "progress",
percentage: 42
}
}
)
```
#### Alert
```ruby theme={null}
activitysmith.live_activities.stream(
"customer-ops",
{
content_state: ActivitySmith::LiveActivities.content_state(
title: "Reactivation",
message: "Lumen came back after 2 weeks",
type: ActivitySmith::LiveActivities::TYPE_ALERT,
icon: ActivitySmith::LiveActivities.alert_icon("cloud.sun", color: "yellow"),
badge: ActivitySmith::LiveActivities.alert_badge("Customer", color: "magenta")
)
}
)
```
#### Timer
```ruby theme={null}
activitysmith.live_activities.stream(
"benchmark-run",
{
content_state: {
title: "Benchmark Run",
subtitle: "sampling",
type: "timer",
duration_seconds: 300,
color: "cyan"
}
}
)
```
For a countdown, send `duration_seconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `duration_seconds` out unless you want to change the timer.
To start at 00:00 and count up, set `counts_down: false` and leave out `duration_seconds`.
### End Live Activity
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.
```ruby theme={null}
activitysmith.live_activities.end_stream(
"prod-web-1",
{
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 7, unit: "%" },
{ label: "MEM", value: 38, unit: "%" }
],
auto_dismiss_minutes: 2
}
}
)
```
### Icons and Badges
Add more context to Live Activities with icons and badges.
#### Icon
Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.
```ruby theme={null}
activitysmith.live_activities.stream(
"prod-web-1",
{
content_state: ActivitySmith::LiveActivities.content_state(
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
icon: ActivitySmith::LiveActivities.alert_icon("server.rack", color: "blue"),
metrics: [
{ label: "CPU", value: 18, unit: "%" },
{ 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](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use
* [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app
* [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography
#### Badge
Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities.
```ruby theme={null}
activitysmith.live_activities.stream(
"nightly-database-backup",
{
content_state: ActivitySmith::LiveActivities.content_state(
title: "Nightly Database Backup",
subtitle: "verify restore",
type: "progress",
badge: ActivitySmith::LiveActivities.alert_badge("S3", color: "cyan"),
percentage: 62
)
}
)
```
### Live Activity Colors
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`
### Live Activity Action
Live Activities can include an action button.
* `open_url`: open an HTTPS URL.
* `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app.
* `webhook`: trigger a backend GET/POST workflow.
#### Open URL action
```ruby theme={null}
activitysmith.live_activities.stream(
"prod-web-1",
{
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 76, unit: "%" },
{ label: "MEM", value: 52, unit: "%" }
]
},
action: {
title: "Dashboard",
type: "open_url",
url: "https://status.example.com/servers/prod-web-1"
}
}
)
```
#### Apple Shortcut action
```ruby theme={null}
activitysmith.live_activities.stream(
"prod-web-1",
{
content_state: {
title: "Server Health",
subtitle: "prod-web-1",
type: "metrics",
metrics: [
{ label: "CPU", value: 76, unit: "%" },
{ label: "MEM", value: 52, unit: "%" }
]
},
action: {
title: "Chat with Jarvis",
type: "open_url",
url: "shortcuts://run-shortcut?name=Jarvis"
}
}
)
```
#### Webhook action
```ruby theme={null}
activitysmith.live_activities.stream(
"search-reindex",
{
content_state: {
title: "Reindexing product search",
subtitle: "Shard 7 of 12",
type: "segmented_progress",
number_of_steps: 12,
current_step: 7
},
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-ruby"
}
}
}
)
```
#### Secondary action

Use `secondary_action` when you want a second button beside the primary `action`.
The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes.
```ruby theme={null}
activitysmith.live_activities.stream(
"agent-approval",
{
content_state: ActivitySmith::LiveActivities.content_state(
title: "Approval Needed",
message: "Should I send the follow-up email to Brightlane?",
type: "alert",
color: "green",
icon: ActivitySmith::LiveActivities.alert_icon("sparkles", color: "green"),
badge: ActivitySmith::LiveActivities.alert_badge("Agent", color: "green")
),
action: {
title: "Send",
type: "webhook",
url: "https://agent.example.com/live-activity/approve",
method: "POST",
body: {
approval_id: "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
decision: "send"
}
},
secondary_action: {
title: "Deny",
type: "webhook",
url: "https://agent.example.com/live-activity/deny",
method: "POST",
body: {
approval_id: "approval_01JY3J7Q9S0P8M1V5PZK7DR4M2",
decision: "deny"
}
}
}
)
```
## Channels
Target specific channels when sending a push notification or streaming a Live Activity.
```ruby Ruby theme={null}
activitysmith.notifications.send(
{
title: "New subscription 💸",
message: "Customer upgraded to Pro plan",
channels: ["ios-builds", "engineering"]
}
)
activitysmith.live_activities.stream(
"nightly-backup",
{
channels: ["ios-builds"],
content_state: {
title: "Nightly database backup",
number_of_steps: 3,
current_step: 1,
type: "segmented_progress"
}
}
)
```
## Widgets
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.
Use the metric key to update its value.
```ruby theme={null}
activitysmith.metrics.update("deploy.success_rate", 99.9)
```
String metric values work too.
```ruby theme={null}
activitysmith.metrics.update("prod.status", "healthy")
```
## Error Handling
Handle API errors with `begin/rescue` around SDK calls:
```ruby Ruby theme={null}
begin
activitysmith.notifications.send(
{ title: "Hello" }
)
rescue OpenapiClient::ApiError => err
puts "Request failed: #{err.code} #{err.message}"
end
```
## Additional Resources
Install the ActivitySmith Ruby SDK from RubyGems
View the Ruby SDK source on GitHub
# Team Members
Source: https://activitysmith.com/docs/team
Manage your team from one place: invite members, track pending invites, and remove access.
## Managing Team Members
The **Members** page is where team owners manage access for the whole workspace.
You can:
* Invite one or many people at once
* See active users and their role
* Track pending invitations and expiration dates
* Remove members when they no longer need access
## Roles
ActivitySmith currently supports two team roles:
| Role | Access |
| -------- | ------------------------------------------------------------- |
| `owner` | Full access, including inviting and removing members |
| `member` | Standard workspace access without team management permissions |
## Invite Team Members
Only team owners can invite new members.
1. Open your ActivitySmith dashboard.
2. Go to **Members** in the left sidebar.
3. Click **Invite members**.
4. Enter one or more email addresses in the invite modal.
5. Separate multiple emails with commas or new lines.
6. Click **Send Invites**.
Newly invited users appear in the **Invited users** table with:
* `pending` status until accepted
* Invite date (`Invited`)
* Expiration date (`Expires`)
Members are added to **Active users** only after they accept the invite.
## Remove a Member
Only team owners can remove members.
1. Open **Members**.
2. Find the user in **Active users**.
3. Click **Remove** in the **Actions** column.
4. Confirm the removal.
The removed member loses team access immediately.
# Widgets
Source: https://activitysmith.com/docs/widgets
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.
## How It Works
1. Create a metric in the web app.
2. Update the value using API anytime it changes.
3. Add the widget to your iPhone Lock Screen.
4. The widget fetches the latest value about every 15 minutes. iOS manages the refresh schedule.
When creating a metric, you can choose the format: number, currency, percent, unit, or string.
## Updating Metric Value
Use the metric key when sending updates. Values can be numbers or strings.
```js Node theme={null}
import ActivitySmith from "activitysmith";
const activitysmith = new ActivitySmith({
apiKey: process.env.ACTIVITYSMITH_API_KEY,
});
await activitysmith.metrics.update("deploy.success_rate", 99.9);
```
```python Python theme={null}
import os
from activitysmith import ActivitySmith
activitysmith = ActivitySmith(api_key=os.environ["ACTIVITYSMITH_API_KEY"])
activitysmith.metrics.update("deploy.success_rate", 99.9)
```
```go Go theme={null}
package main
import (
"log"
activitysmithsdk "github.com/ActivitySmithHQ/activitysmith-go"
)
func main() {
activitysmith, err := activitysmithsdk.New("YOUR-API-KEY")
if err != nil {
log.Fatal(err)
}
_, err = activitysmith.Metrics.Update("deploy.success_rate", 99.9)
if err != nil {
log.Fatal(err)
}
}
```
```php PHP theme={null}
metrics->update('deploy.success_rate', 99.9);
```
```ruby Ruby theme={null}
require "activitysmith"
activitysmith = ActivitySmith::Client.new(api_key: ENV.fetch("ACTIVITYSMITH_API_KEY"))
activitysmith.metrics.update("deploy.success_rate", 99.9)
```
```bash cURL theme={null}
curl -X POST "https://activitysmith.com/api/metrics/deploy.success_rate/value" \
-H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "value": 99.9 }'
```
For the full API reference, see [Update Metric Value](/docs/api-reference/endpoint/metric-value-update).