> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Data & background notifications

> Send silent push notifications to sync data or trigger background tasks on iOS and Android without displaying a visible message.

Use silent notifications to wake your app and run background work, such as syncing or refreshing data, without showing a message or playing a sound. Send one by setting `content_available` to `true` and omitting all visible content, then handle the payload in native code.

On iOS these are called **background notifications**, and on Android they're called **data notifications**. Both are commonly called silent pushes. They behave differently from visible notifications in one way that shapes everything else on this page: delivery is best-effort, so no silent push is guaranteed to arrive.

## Limitations

* **Apps cannot receive silent pushes if**:
  * **iOS**: The app has been closed by the user, such as swiping it away from the app switcher. (See [Apple support](https://support.apple.com/en-us/HT201330)).
  * **Android**: The app has been force-quit via device settings or automatically by some manufacturers when swiped away. ([Android force-stop behavior](./notifications-show-successful-but-are-not-being-shown#android-force-stop)).
* **Delivery is not guaranteed**:
  * Both Apple and Google treat silent notifications as *best-effort*. iOS may delay or drop delivery under Low Power Mode, Background App Refresh off, or if the app was closed by the user. Android may throttle or batch delivery under Doze or OEM power-saving rules.
  * Apple's stated ceiling is two or three background notifications per hour: "The number of background notifications allowed by the system depends on current conditions, but don't try to send more than two or three per hour." See [Pushing background updates to your app](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app). Sending more does not raise the ceiling, it just gets more of them dropped.
  * iOS throttles against an energy and data budget for the whole device, so silent pushes to other apps consume the same budget, and the budget resets about once a day. Apple disables this throttle when you run your app from Xcode, which is why silent pushes look far more reliable in testing than in production. See [Technical Note TN2265](https://developer.apple.com/library/archive/technotes/tn2265/_index.html).
  * Because of this, **silent notifications should never be used for critical updates**.
* **Background execution is time-boxed**: iOS gives your app about 30 seconds to finish its work and call the completion handler. Start long transfers with a background session rather than trying to complete them inline.
* **Subscribed users only**: OneSignal only sends data notifications to subscribed [Subscriptions](./subscriptions).
* **Limited support for cross-platform SDKs**:
  * Silent notifications must be handled in native code (Java/Kotlin for Android, Swift/Obj-C for iOS). Wrapper SDKs such as React Native and Flutter have no cross-platform handler for them.
  * iOS requires implementation of [`application:didReceiveRemoteNotification:fetchCompletionHandler:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application).
  * Android requires a [notification service extension](./service-extensions#android-notification-service-extension).

***

## Sending silent notifications from OneSignal

Follow these steps to send a silent notification from OneSignal:

<Steps>
  <Step title="Omit visible content">
    Remove any visible text or titles from the message. This includes:

    * **API**: `contents`, `headings`, `subtitle` in your [Create notification](/reference/create-message) API request.
    * **Dashboard**: Message, Title, Subtitle
  </Step>

  <Step title="Set content_available">
    * **API**: Set `content_available` to `true`.
    * **Dashboard**: Check **Content available** under "Send to Apple iOS". Despite the label, this setting applies to all platforms and signals to OneSignal that no visible message is included.
  </Step>

  <Step title="Add data to the notification">
    * **API**: Use the `data` parameter.
    * **Dashboard**: Use the **Additional Data** fields.
  </Step>

  <Step title="Set priority to 5">
    **API**: Set `priority` to `5`. The default of `10` is the wrong value for a silent push.
  </Step>
</Steps>

<Warning>
  Send silent pushes with `priority: 5`, not the default `10`. Apple requires normal priority for background notifications and may reject or throttle high-priority ones. On Android, FCM watches for high-priority messages that never produce a visible notification and [deprioritizes the app's messages](./notifications-show-successful-but-are-not-being-shown#android-doze-mode-priority-and-deprioritized-messages) when it detects that pattern, which degrades delivery for your visible notifications too.
</Warning>

### Example API payload

```curl curl theme={null}
curl -X POST https://api.onesignal.com/notifications \
  -H "Authorization: Key YOUR_APP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "app_id": "YOUR_APP_ID",
    "include_aliases": { "external_id": ["user-123"] },
    "target_channel": "push",
    "content_available": true,
    "priority": 5,
    "data": {
      "action": "sync_data",
      "version": "2"
    }
  }'
```

The `data` object is what your app reads when the push arrives. It reaches your code as `userInfo["custom"]["a"]` on iOS and as `additionalData` on Android, both shown in [Platform-specific setup](#platform-specific-setup) below.

***

## Platform-specific setup

### iOS background notification setup

Your iOS app must have the **Background Modes > Remote notifications** capability enabled in Xcode. You already have it if you followed [Enable Push Notifications and Background Modes](./ios-sdk-setup#step-1-enable-push-notifications-and-background-modes) during SDK setup. Without it, iOS never wakes your app for a silent push.

To process the notification, implement the `AppDelegate` method [`application(_:didReceiveRemoteNotification:fetchCompletionHandler:)`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application). OneSignal nests the `data` object you sent under the `a` key of the `custom` dictionary in `userInfo`.

```swift AppDelegate.swift theme={null}
func application(
    _ application: UIApplication,
    didReceiveRemoteNotification userInfo: [AnyHashable: Any],
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
    guard let customData = userInfo["custom"] as? [String: Any],
          let additionalData = customData["a"] as? [String: Any],
          let action = additionalData["action"] as? String else {
        completionHandler(.noData)
        return
    }

    // iOS allows roughly 30 seconds of work. Always call the completion handler,
    // including on the failure path, or iOS throttles future background pushes.
    switch action {
    case "sync_data":
        syncData { didChange in
            completionHandler(didChange ? .newData : .noData)
        }
    default:
        completionHandler(.noData)
    }
}
```

Apple documentation:

* [Pushing background updates to your app](https://developer.apple.com/documentation/usernotifications/pushing-background-updates-to-your-app)
* [Generating a remote notification](https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification)

<Warning>
  If the user has closed the app (swiped it away from the app switcher), iOS will not deliver the notification.

  In such cases, include a visible `contents` message and process the data in [`UNNotificationServiceExtension.didReceive`](./service-extensions#ios-notification-service-extension) instead.
</Warning>

***

### Android data notification setup

Handle data notifications in a [notification service extension](./service-extensions#android-notification-service-extension). Your class implements `INotificationServiceExtension`, and its `onNotificationReceived` method runs whenever a push arrives, whether or not the push has visible content. Read the `data` object you sent from `notification.additionalData`.

<CodeGroup>
  ```kotlin Kotlin theme={null}
  @Keep
  class NotificationServiceExtension : INotificationServiceExtension {
      override fun onNotificationReceived(event: INotificationReceivedEvent) {
          val action = event.notification.additionalData?.optString("action", "") ?: ""

          if (action == "sync_data") {
              // A silent push has no content to display, so there is nothing to
              // prevent or show. Hand the work to WorkManager to survive Doze.
              scheduleSync(event.context)
          }
      }
  }
  ```

  ```java Java theme={null}
  @Keep
  public class NotificationServiceExtension implements INotificationServiceExtension {

      @Override
      public void onNotificationReceived(INotificationReceivedEvent event) {
          JSONObject additionalData = event.getNotification().getAdditionalData();
          String action = additionalData != null ? additionalData.optString("action", "") : "";

          if (action.equals("sync_data")) {
              // A silent push has no content to display, so there is nothing to
              // prevent or show. Hand the work to WorkManager to survive Doze.
              scheduleSync(event.getContext());
          }
      }
  }
  ```
</CodeGroup>

Register the class in your `AndroidManifest.xml`. Without that manifest entry, the extension never runs.

Android documentation:

* [FCM data messages](https://firebase.google.com/docs/cloud-messaging/concept-options#data_messages)
* [Optimize for Doze and App Standby](https://developer.android.com/training/monitoring-device-state/doze-standby)

<Warning>
  If the app has been force-stopped (via device settings or by some OEM battery optimization), Android will not deliver the notification. See [Android force-stop behavior](./notifications-show-successful-but-are-not-being-shown#android-force-stop).
</Warning>

***

### Huawei (HMS) data notification setup

On Huawei devices, OneSignal chooses how to deliver each push to HMS using the [`huawei_msg_type`](/reference/push-notification#body-huawei-msg-type) API parameter:

* **`data`**: HMS delivers the payload to the device and the OneSignal SDK processes it client-side. This is the type you need for **silent** notifications on Huawei, and it's also what the SDK uses to render *visible* full-featured notifications (images, buttons, confirmed delivery).
* **`message`**: HMS Core handles the notification server-side and displays a title and body only. Use `data` if you need silent delivery or background processing.

<Warning>
  `huawei_msg_type=data` is **not** the same as a silent notification. It's the HMS *transport type*. A `data`-type push that includes visible content (`contents`/`headings`) still displays a full notification. The SDK renders it locally. To send a *silent* push on Huawei, use `huawei_msg_type=data` **and** omit visible content (follow the [steps above](#sending-silent-notifications-from-onesignal)).
</Warning>

As with Android, if the app has been force-stopped, HMS Core will not start it to process the notification, so a `data`-type push won't be delivered. See [Android force-stop behavior](./notifications-show-successful-but-are-not-being-shown#android-force-stop).

***

## Sending VoIP notifications

VoIP notifications are supported but require additional configuration outside the standard OneSignal SDKs. OneSignal does not register VoIP tokens automatically.

<Card title="VoIP Notifications Setup Guide" icon="phone" href="./voip-notifications">
  Configure VoIP push notifications for real-time calling on iOS.
</Card>

***

## FAQ

### What priority should I use for silent notifications?

Use `priority: 5`. The API defaults to `10`, which is wrong for a silent push on both platforms. Apple requires normal priority for background notifications, and FCM deprioritizes an app's messages when it detects high-priority sends that never produce a visible notification, which then degrades delivery of your visible notifications. See [Android Doze mode, priority, and deprioritized messages](./notifications-show-successful-but-are-not-being-shown#android-doze-mode-priority-and-deprioritized-messages).

### Do confirmed deliveries work with silent notifications?

**Android**: Yes, if the app has not been force-stopped. See [Android force-stop behavior](./notifications-show-successful-but-are-not-being-shown#android-force-stop).

**iOS**: No. Confirmed receipt on iOS depends on the Notification Service Extension running when the push arrives, and iOS only launches that extension for notifications that will display. A silent push never launches it, so no receipt is reported. See [Confirmed delivery](./confirmed-delivery).

### Can silent notifications be used to detect uninstalls or unsubscribes?

Not reliably. Silent notifications are best-effort and not guaranteed to be delivered, as explained in the [Limitations](#limitations) section.

Instead:

* Send visible notifications (with content) to all your users at least once a month.
* Optionally send silent notifications as a supplemental check.

For more details on handling subscription status changes, see the [Subscriptions](./subscriptions) guide.

### Can I use silent notifications to measure how many users are reachable?

No. Silent notifications are best-effort, so they can be delayed or dropped, and they don't trigger confirmed delivery callbacks, so you have no reliable way to know which users received the push. See [Limitations](#limitations) for details.

To measure reachable users, send a visible notification and track delivery metrics in [Analytics](./analytics-overview).

***

## Related pages

<Columns cols={2}>
  <Card title="Service extensions" icon="puzzle-piece" href="./service-extensions">
    Handle notification processing in native code on iOS and Android.
  </Card>

  <Card title="Subscriptions" icon="address-book" href="./subscriptions">
    Understand Subscription types and how they connect to Users.
  </Card>

  <Card title="Create Message API" icon="code" href="/reference/create-message">
    Send notifications programmatically, including silent pushes.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.