Skip to main content
Live Activities let your iOS app show real-time updates directly on the Lock Screen and Dynamic Island. Ideal for delivery tracking, sports scores, or time-sensitive transactional updates, they keep users informed without opening the app.
Android has a similar feature called Live Updates.

Requirements

  • Follow the iOS SDK setup if using native iOS (Swift/Objective-C).
  • OneSignal iOS SDK version 5.2.0+ for push-to-start support (see release notes).
  • OneSignal iOS SDK version 5.2.15+ for click tracking and confirmed receipt.
  • iOS 16.1+ or iPadOS 17+ allows starting Live Activities in-app.
  • iOS 17.2+ allows starting Live Activities remotely.
  • A .p8 APNs key. Apple does not support p12 certificates with Live Activities.
  • Xcode 14 or higher.

Setup

These steps walk you through setting up Live Activities quickly. For more details and design customizations, see Apple’s Live Activities Developer docs.

1. Add a Widget Extension

In Xcode, go to File > New > Target… > Widget Extension.
Xcode new target dialog with Widget Extension selected

Add a new Widget Extension target for your app in Xcode.

Select and press Next. Configure the Widget Extension by providing a name (example: OneSignalWidget) and ensure Include Live Activity is selected. Then click Finish.
Widget Extension configuration with Include Live Activity checkbox selected

Widget Extension options for a Live Activity.

Click Don’t Activate if prompted to activate the scheme.
Xcode scheme activation dialog for the Widget Extension

Scheme activation prompt: select Don't Activate.

2. Update Info.plist

In your main target’s Info.plist, add the key Supports Live Activities as Boolean, and set it to YES.
Xcode Info.plist editor showing Supports Live Activities set to YES

Add Supports Live Activities key to Info.plist and set its value to Boolean YES.

If you set it programmatically, it should look like this:
Info.plist
If your use case sends frequent high-priority updates, add NSSupportsLiveActivitiesFrequentUpdates to your Info.plist as a Boolean set to YES (iOS 16.2+). This raises the budget Apple imposes on priority: 10 updates. See Update frequency and throttling.

3. Add SDK

If you are using a wrapper SDK (e.g. Flutter) with SPM enabled, you can skip this step. The OneSignal package is already resolved and available to all targets.
In your Widget Extension target, add the OneSignalFramework under General > Frameworks, Libraries and Embedded Content:
Xcode Frameworks and Libraries section with OneSignalFramework added

Add the OneSignalFramework to your Widget Extension target.

4. Define widget attributes and UI

Open the your-nameLiveActivity.swift file (example: OneSignalWidgetLiveActivity.swift) to define the properties of the struct and to make changes to the widget UI.
  • your-nameAttributes describes the static content of your Live Activity.
  • ContentState describes the dynamic content of your Live Activity.
Send any Date-typed field in your custom Attributes or ContentState struct as a Unix timestamp in seconds, not as an ISO 8601 string and not in milliseconds. ActivityKit decodes date values in the push payload as seconds since 1970, and your app cannot change that strategy. To avoid the ambiguity, declare the field as a Double of Unix seconds and convert it in your widget. OneSignal’s stale_date and dismissal_date parameters are also Unix timestamps in seconds.
If you are following the example, copy-paste the code below into your OneSignalWidgetLiveActivity.swift file.
your-nameLiveActivity.swift

5. Allow main target membership

This step is only required when using custom attributes (e.g., OneSignalWidgetAttributes). If you are using DefaultLiveActivityAttributes, skip this step. The type is provided by the OneSignal SDK and is already accessible from your main app target.
Add your main app target to the Target Membership list in the your-nameLiveActivity.swift file. This is necessary so the main app target can reference your custom attributes struct in the setup call (Step 6). In Xcode, open the Inspector panel on the right side of the screen. Within Target Membership, click the + button and select your main app target containing the ContentView and your OneSignal initialization code.
Xcode Inspector panel showing Target Membership with the main app target checked

Allow main target membership.

6. Add the setup method to your AppDelegate

Call OneSignal.LiveActivities.setup in your AppDelegate, after OneSignal SDK initialization. Replace OneSignalWidgetAttributes with the name of your Live Activity attributes struct.
AppDelegate
This manages and reports updates using ActivityKit async sequences.
The OneSignal SDK automatically observes the following ActivityKit async sequences. While Apple hasn’t documented whether these sequences support multiple observers, our testing hasn’t revealed any issues. However, if your app also directly observes these sequences, be aware of potential conflicts:
  • activityStateUpdates
  • pushTokenUpdates
  • pushToStartTokenUpdates
  • activityUpdates
See Troubleshooting: Conflicts with ActivityKit async sequences for resolution steps.

Starting a Live Activity

There are 2 options to start a Live Activity on a device:
Send a Push To Start API request. Be sure all names and IDs match your widget’s configuration exactly (parameters are case-sensitive). If anything is missing or incorrectly added, you may encounter issues when trying to launch the widget.Here is an example request that will work for the example above.Replace:
  • YOUR_APP_ID with your OneSignal App ID.
  • YOUR_APP_API_KEY with your OneSignal API key.
  • OneSignalWidgetAttributes with the name of your Widget Attributes struct.
This example uses the fixed activity_id of push-to-start so you can test quickly. In production, choose the value deliberately: it is the key that determines which devices a later update reaches. See Choose an activity ID.If you are following the example code provided, you should see the Live Activity on your device’s Lock Screen.
iPhone Lock Screen displaying a Live Activity started via push-to-start

Live Activity on the Lock Screen.

You successfully started a Live Activity with push-to-start!Users will need to select “Allow” to continue getting updates.

Tracking Live Activity clicks

Track when users tap on your Live Activities and Dynamic Islands by implementing OneSignal’s click tracking. This enables you to measure engagement and optionally deep link users to specific content in your app.

Step 1: Add Click Tracking to Your Widget

Add the .onesignalWidgetURL() modifier to any UI component in your Live Activity widget that you want to track clicks on:
Important Considerations:
  • You can pass a URL for deep linking or nil if you only want click tracking without navigation
  • The view hierarchy cannot include Apple’s .widgetURL() modifier if you’re using .onesignalWidgetURL()
  • Apply the modifier to both the main Live Activity view and Dynamic Island if you want to track clicks on both

Step 2: Handle URLs in Your App

Add URL handling in your app to track clicks and route users appropriately:
The trackClickAndReturnOriginal() method automatically tracks the click with OneSignal and returns the original URL you specified in the widget for your app to handle.

Updating a Live Activity

Use the Update Live Activity API to update active widgets. Match the activity_id used when starting the activity. This example request updates the push-to-start widget because it has the activity_id of push-to-start defined when starting the activity. To update the click-to-start widget, update the request path to use click-to-start instead of push-to-start.
iPhone Lock Screen showing an updated Live Activity with new content

Live Activity updated on the Lock Screen.

You successfully updated a Live Activity!Check out the Update Live Activity API for more information on updating a Live Activity.

Ending a Live Activity

Using the same Update Live Activity API, you can end a Live Activity by setting "event": "end".
This request ends the activity, but iOS keeps it on the Lock Screen for up to 4 hours afterward. To remove it sooner, include a dismissal_date. See End a Live Activity. Other ways a Live Activity can end:
  • Use our SDK exit() method.
  • User manually swipes the Live Activity away.
  • User revokes permission for Live Activities in their iOS Settings.
iPhone Lock Screen showing an ended Live Activity

Live Activity ended on the Lock Screen.

You successfully ended the Live Activity and completed the example!

Best practices & recommendations

Design considerations

  • Follow Apple’s Live Activities Human Interface Guidelines.
    • Prioritize important information to make it easy to understand at a quick glance.
    • Don’t add elements to your app that draw attention to the Dynamic Island.
    • Use margins and maintain space between elements.
    • Use a bold color for the background. Design for both Light and Dark mode.

Functionality

Setting a fallback message

If a user cannot receive an update after a Live Activity has started, opening the app should refresh the activity. Set the stale date to a point in the future after you expect to have sent the first update. Users who have not received the update are shown the fallback message instead. You can listen for the “stale” state in your widget UI to show a fallback message:
Live Activity widget displaying a fallback message prompting the user to tap to refresh

Fallback message shown when a Live Activity becomes stale.

Live Activity permission observer

When a user first sees a Live Activity, iOS prompts them to allow or disallow updates. If they select “Don’t Allow”, they do not receive further updates. Use an observer to listen for changes in the user’s Live Activity permission status.
iOS prompt asking the user to allow or disallow Live Activity updates

iOS Live Activity permission prompt.


FAQ

How often can I update a Live Activity?

As often as you need when you send priority: 5. Those updates deliver opportunistically and are unmetered by Apple, so there is no limit on how many you send. Only priority: 10 is metered. Apple does not publish the size of the budget: iOS calculates it dynamically per device, then delays or drops updates once you exceed it. To reduce the risk of throttling:
  • Set priority: 5 for routine updates. When you omit priority, OneSignal sends 10 and spends budget, so set it explicitly.
  • Reserve priority: 10 for updates that need the user’s immediate attention, such as order status changes or game scores.
If your use case requires frequent updates:
  • Add the key NSSupportsLiveActivitiesFrequentUpdates to your app’s Info.plist file, set as a Boolean YES.
  • When this budget is exceeded, iOS may prompt the user to allow additional updates. If the user agrees, Apple will automatically expand the allowed update limit to maintain a seamless experience.
For more details, see Update frequency and throttling and Apple’s Developer Docs.

Can I read Live Activity updates from the main app?

Yes. You can observe updates for debugging or UI sync:
Track lifecycle changes:

The API returned a 400 with an error message stating I’m over the subscriber limit. What do I do?

If your push subscriber count exceeds your plan’s limit, upgrade your account to the next plan or contact support@onesignal.com. See the Pricing page for plan details.

How do I avoid sending both push and Live Activities?

Your application may already send a series of Push Notifications, where your designed Live Activity replaces the need for these Push Notifications. For example, if you send score updates via Push, you could replace this through a Live Activity. When a user opts in for a Live Activity, add a data tag to their profile. You can then exclude users with that tag from push messages that contain the same or similar content using Segments.

Troubleshooting

No recipients

For users to be found when starting or updating a Live Activity, the activity type, widget, and API request must all have matching values.
  1. Check the path parameters in your request to ensure that you are sending a correctly formatted request to the server. The App ID must match your App ID used in the OneSignal.Initialize method and the activity type must match that of the type you’ve defined in your Live Activity file.
  2. In the body of the Push To Start API request, you should have the following parameters:
  • event: "start"
  • event_updates: The dynamic data you have defined in your struct under activity type and that is used in your widget. Ensure the letter casing and variables all match between the request, the type, and the widget. Any Date fields must be sent as Unix timestamps, not ISO 8601 strings.
  • event_attributes: Static data follows the same logic as Event Updates and must include all variables in use, and must match across all parts of the live activity and the request
  • activity_id: This will assign an ID to the widget and is what will be used to update the activity after it has been launched on the user’s device. See Choose an activity ID.
  • name: The Live Activity Name.
  • contents: The message content required for sending push.
  • headings: The message heading required for sending push.
  • A targeting parameter like included_segments. Available options.

Activity sent, but not received

  1. Check the Confirmed Receipt count first. In your message report, if you see a Confirmed Receipt count, this means Apple successfully delivered the update to the device. The issue is likely that the device is preventing the widget from displaying, not a delivery problem. This could be due to:
    • The Live Activity being dismissed by the user
    • Widget configuration issues within the app
  2. Ensure that the request is formatted correctly. If any fields that are used in the Widget are omitted, the activity may not launch or update as expected.
Send any Date-typed field in your custom Attributes or ContentState struct as a Unix timestamp in seconds, not as an ISO 8601 string and not in milliseconds. ActivityKit decodes date values in the push payload as seconds since 1970, and your app cannot change that strategy. To avoid the ambiguity, declare the field as a Double of Unix seconds and convert it in your widget. OneSignal’s stale_date and dismissal_date parameters are also Unix timestamps in seconds.
  1. In your API request, check the priority level. If you are sending 10, try 5 and test again. Only priority: 10 counts against Apple’s budget, and exceeding it causes throttling. If your use case needs frequent high-priority updates, add NSSupportsLiveActivitiesFrequentUpdates to your Info.plist as a Boolean set to YES. See Update frequency and throttling.

Conflicts with ActivityKit async sequences

If you’re experiencing issues with Live Activities not updating properly or unexpected behavior, check if your app is directly observing the same ActivityKit async sequences that OneSignal monitors:
  • activityStateUpdates
  • pushTokenUpdates
  • pushToStartTokenUpdates
  • activityUpdates
Since Apple hasn’t documented whether these sequences support multiple concurrent observers, having both OneSignal and your app observe the same sequences may cause conflicts. To resolve:
  1. Remove direct observation of these sequences from your app code if possible
  2. Use OneSignal.LiveActivities.setup() which handles all observation automatically. Avoid manually observing sequences when using this method
  3. If you must use the low-level approach with enter()/exit() and manual token observation, ensure your implementation doesn’t prevent OneSignal from receiving updates
Need help?Chat with our Support team or email support@onesignal.comPlease include:
  • Details of the issue you’re experiencing and steps to reproduce if available
  • Your OneSignal App ID
  • The External ID or Subscription ID if applicable
  • The URL to the message you tested in the OneSignal Dashboard if applicable
  • Any relevant logs or error messages
We’re happy to help!