Skip to main content

Documentation Index

Fetch the complete documentation index at: https://activitysmith.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

ActivitySmith Live ActivitiesActivitySmith Push Notifications

Welcome to ActivitySmith

ActivitySmith 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, 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: Want an SDK or Integration? Let us know at adam@activitysmith.com.

Prerequisites

Features

  • Push Notifications: send push notifications to all paired devices or target specific channels.
  • 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: display any value on your Lock Screen with widgets - SaaS metrics, revenue, signups, uptime, habits, or anything else you want to track.
  • 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 on normal tap.
  • actions (up to 4) appear when users expand the notification.
  • media + redirection is supported.
  • media + actions is not supported in v1.
Push Notification
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"
  }'
Response
{
  "success": true,
  "devices_notified": 3,
  "users_notified": 1,
  "timestamp": "2025-08-12T12:00:00.000Z"
}

Live Activities

There are four types of Live Activities:
TypeBest forRequired state
statsup to 8 labeled valuestitle, type, and a non-empty metrics array
metricsLive operational statstitle, type, and a non-empty metrics array
segmented_progressJobs tracked in stepstitle, type, number_of_steps, current_step
progressJobs with continuous progresstitle, type, and either percentage or value + upper_limit
Stats Live Activity Metrics Live Activity update Progress Live Activity start Segmented Progress Live Activity update When working with Live Activities via our API, you have two approaches tailored to different needs.

Simple: stream updates

Use stream updates when you want the easiest, stateless flow. Send the latest state for a stable stream_key, and ActivitySmith starts or updates the Live Activity for you. You do not need to store activity_id or manage the lifecycle yourself.

Advanced: full lifecycle control

Use the lifecycle endpoints when you want full control over a specific Live Activity instance.
  1. Call POST /live-activity/start.
  2. Save the returned activity_id.
  3. Call POST /live-activity/update whenever progress changes.
  4. Call POST /live-activity/end when the work is finished.

Start response

Starting a Live Activity returns the activity_id you will use for later updates and for the final end call.
{
  "success": true,
  "activity_id": "pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW",
  "devices_notified": 2,
  "users_notified": 1,
  "timestamp": "2026-01-28T09:57:22.929Z"
}

Stats Type

Stats supports up to 8 items in the metrics array. Each metric takes a label, and a formatted string or numeric value. Add an optional color when you want a small visual cue. Leave it out when you want plain text.

Stream

Use a stable stream_key and send the latest values whenever they change. ActivitySmith starts the Live Activity on the first call and updates it on subsequent calls, so you do not need to store activity_id. Stats Live Activity stream
curl -X PUT https://activitysmith.com/api/live-activity/stream/sales-hourly \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "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 Type

Use metrics to keep a small set of live numbers visible on the Lock Screen and Dynamic Island. It fits server health, queue pressure, replica lag, worker saturation, and similar backend state you want to glance at without opening a dashboard. Each entry in the metrics array takes a label, a numeric value, and an optional unit.

Stream

Use a stable stream_key (such as a server, deployment, or job name) and send the latest values whenever they change. ActivitySmith starts the Live Activity on the first call and updates it on subsequent calls - you do not need to track activity_id. Metrics Live Activity stream
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": 9, "unit": "%" },
        { "label": "MEM", "value": 45, "unit": "%" }
      ]
    }
  }'
Call the same stream_key again whenever values change to update the Live Activity in place. Metrics Live Activity stream update

End the stream

When the tracked process is finished, end the stream so the Live Activity is removed from devices. content_state is optional - include it to end with a final state.
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
    }
  }'

Segmented Progress Type

Use segmented_progress for jobs and workflows that move through clear steps or phases. It fits jobs like backups, deployments, ETL pipelines, and checklists. number_of_steps is dynamic, so you can increase or decrease it later if the workflow changes.

Start

Start with title, type: "segmented_progress", number_of_steps, and current_step. Add subtitle, color, and target.channels if needed. Segmented Progress Live Activity start
curl -X POST https://activitysmith.com/api/live-activity/start \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content_state": {
      "title": "Nightly database backup",
      "subtitle": "create snapshot",
      "number_of_steps": 3,
      "current_step": 1,
      "type": "segmented_progress",
      "color": "yellow"
    }
  }'

Update

Update the same activity with activity_id and the latest current_step. If the workflow changes, you can also increase or decrease number_of_steps. Segmented Progress Live Activity update
curl -X POST https://activitysmith.com/api/live-activity/update \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "activity_id": "pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW",
    "content_state": {
      "title": "Nightly database backup",
      "subtitle": "upload archive",
      "current_step": 2
    }
  }'

End

End the activity with the final state. You can send the latest current_step, adjust number_of_steps if needed, and optionally set auto_dismiss_minutes. Segmented Progress Live Activity end
curl -X POST https://activitysmith.com/api/live-activity/end \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "activity_id": "pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW",
    "content_state": {
      "title": "Nightly database backup",
      "subtitle": "verify restore",
      "current_step": 3
    }
  }'

Progress Type

Use progress when the state is naturally continuous. It fits charging, downloads, sync jobs, uploads, timers, and any flow where a percentage or numeric range is the clearest signal.

Start

Start with title, type: "progress", and either percentage or value plus upper_limit. Add subtitle, color, and target.channels if needed. Progress Live Activity start
curl -X POST https://activitysmith.com/api/live-activity/start \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content_state": {
      "title": "EV Charging",
      "subtitle": "Added 30 mi range",
      "percentage": 15,
      "type": "progress",
      "color": "lime"
    }
  }'

Update

Update the same activity with activity_id and the latest percentage, or send value with upper_limit. Progress Live Activity update
curl -X POST https://activitysmith.com/api/live-activity/update \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "activity_id": "pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW",
    "content_state": {
      "title": "EV Charging",
      "subtitle": "Added 120 mi range",
      "percentage": 60
    }
  }'

End

End the activity with the final value. auto_dismiss_minutes is optional. Progress Live Activity end
curl -X POST https://activitysmith.com/api/live-activity/end \
  -H "Authorization: Bearer $ACTIVITYSMITH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "activity_id": "pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW",
    "content_state": {
      "title": "EV Charging",
      "subtitle": "Added 200 mi range",
      "percentage": 100,
      "auto_dismiss_minutes": 2
    }
  }'

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 start, update, and end calls, and works with all Live Activity types.
Live Activity with an action button on iPhoneMetrics Live Activity with an action button
There are two action types:
  • open_url: opens the provided HTTPS URL in the browser.
  • webhook: ActivitySmith’s backend calls your HTTPS webhook with GET or POST.
The action object accepts:
FieldRequiredDescription
titleyesButton label shown on the Live Activity.
typeyesEither open_url or webhook.
urlyesHTTPS endpoint to open or call.
methodwebhook onlyGET or POST.
bodywebhook onlyOptional JSON payload sent with the webhook request.

open_url

Use open_url when the button should jump the user to a dashboard, run page, or any browser destination tied to the work.
{
  "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.
{
  "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:
{
  "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.