Skip to main content
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 [email protected].

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.

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

Live Activities come in two UI types, but the delivery flow stays the same: start the activity, keep the returned activity_id, update it as state changes, then end it when the work is done.
TypeBest forRequired state
segmented_progressJobs tracked in stepstitle, type, number_of_steps, current_step
progressJobs with continuous progresstitle, type, and either percentage or value + upper_limit
Progress Live Activity start Segmented Progress Live Activity update For segmented_progress, number_of_steps does not need to stay fixed. You can increase or decrease it in later update or end calls if the workflow changes. Live Activities can also include one optional action button. Use open_url when the button should open a browser destination, or webhook when ActivitySmith backend should call your HTTPS webhook.

Shared flow

  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"
}

Update and end response

Update and end calls return the same activity ID plus the delivery result.
{
  "success": true,
  "activity_id": "pLAr-Hnq9ZFW4sxlk43Lhbuok4GLh7UW",
  "devices_notified": 2,
  "timestamp": "2026-01-28T09:57:26.056Z"
}

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
    }
  }'

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.