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

# Test push notifications

> Set up and verify web, iOS, and Android push notifications end to end

# Test push notifications

Use this guide to verify one device on each push platform before testing a
campaign or automation. Use a staging workspace and a test subscriber. Never
ship API keys, APNs private keys, or Firebase service-account JSON in a mobile
app or browser bundle.

## Test checklist

For every platform, verify all of these:

1. The device is registered and appears as `active` in **Settings -> Push -> Devices**.
2. **Send a test push** reports that the provider accepted the notification.
3. The device displays the title, body, image, and icon where supported.
4. Tapping the notification opens the expected HTTPS URL or app deep link.
5. The device's delivered and clicked activity is recorded.
6. Unregistering the device prevents later sends.

## Web

### Setup

Enable web push in **Settings -> Push -> Web**. Add the SDK to a real HTTPS
site, or use `localhost` for development:

```html theme={null}
<script
  async
  src="https://api.sequenzy.com/sequenzy.js"
  data-sequenzy-key="seq_pk_your_key"
  data-sequenzy-company="your_workspace_id"
  data-sequenzy-endpoint="https://api.sequenzy.com"
></script>
<button data-sequenzy-push hidden>Enable notifications</button>
```

Serve `/sequenzy-sw.js` from the same origin as the page:

```js theme={null}
importScripts("https://api.sequenzy.com/sequenzy-sw.js");
```

The permission request must be triggered by a user click. After clicking the
button, check DevTools:

* `Notification.permission` is `granted`.
* An activated service worker controls the page.
* `registration.pushManager.getSubscription()` returns a subscription.
* The subscription registration request returns HTTP `200` or `201`.

### Web verification

Send a test push to the registered device. Confirm the notification arrives
after closing or backgrounding the page, then click it and verify the target
URL. Test again after calling `sequenzy.reset()` and confirm the device is
unlinked from the previous contact.

## iOS with APNs

### Provider setup

In **Settings -> Push -> iOS**:

1. Create an Apple Push Notification authentication key with Push Notifications
   enabled.
2. Upload the `.p8` file.
3. Enter the Apple key ID, Team ID, and app bundle ID.
4. Select **Sandbox** for an Xcode development build and **Production** for
   TestFlight or App Store builds.

The `.p8` file is uploaded to the dashboard and must not be included in the
application.

### App registration

Enable remote notifications and forward the APNs token to your backend. Your
backend registers it with the Sequenzy API:

```swift theme={null}
import UIKit
import UserNotifications

final class PushRegistration: NSObject, UNUserNotificationCenterDelegate {
    func requestPermission() {
        UNUserNotificationCenter.current().requestAuthorization(
            options: [.alert, .badge, .sound]
        ) { granted, error in
            guard granted, error == nil else { return }
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }

    func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    ) {
        let token = deviceToken.map { String(format: "%02x", $0) }.joined()
        // Send `token` to your authenticated backend, never directly with an
        // API key embedded in the app.
    }
}
```

Register the token server-side:

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/push/devices" \
  -H "Authorization: Bearer seq_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "ios",
    "token": "APNS_HEX_DEVICE_TOKEN",
    "email": "test@example.com",
    "deviceName": "QA iPhone"
  }'
```

### iOS verification

Use a physical device, or the iOS Simulator on an Apple silicon Mac with
Xcode 14 or later, which receives Sandbox pushes. Confirm the APNs environment
matches the credential and build, then send a test push. Test both foreground
and background states, tap the notification, and verify the app opens the
supplied deep link.

If the notification contains an image, add a Notification Service Extension
and download the image when `mutable-content` is present. Report `delivered`
and `clicked` events to the `eventsUrl` with the token included in the payload,
as described in [Push notifications](./push-notifications).

## Android with FCM

### Provider setup

In **Settings -> Push -> Android**:

1. Open the Firebase project used by the Android application.
2. Generate a service-account JSON file under **Project settings -> Service
   accounts**.
3. Upload the JSON file and confirm the project ID shown by Sequenzy.

The service-account JSON belongs only in the dashboard or a secure backend.

### App registration

Add Firebase Messaging to the Android app and forward the token to your
backend:

```kotlin theme={null}
class PushMessagingService : FirebaseMessagingService() {
    override fun onNewToken(token: String) {
        // POST the token to your authenticated backend.
        // The backend calls Sequenzy's register-device endpoint.
    }

    override fun onMessageReceived(message: RemoteMessage) {
        val data = message.data
        val title = data["title"] ?: return
        val body = data["body"].orEmpty()
        // Show a notification and retain pushSendId, deviceId, clickToken,
        // and eventsUrl for delivered/clicked reporting.
    }
}
```

Register the token server-side:

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/push/devices" \
  -H "Authorization: Bearer seq_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "platform": "android",
    "token": "FCM_REGISTRATION_TOKEN",
    "email": "test@example.com",
    "deviceName": "QA Pixel"
  }'
```

### Android verification

Use a physical device or an emulator with Google Play services. Test the app
in foreground, background, and after force-closing it. In the foreground,
`onMessageReceived` runs and your app shows the notification. In the
background, Android shows it for you, and a tap opens your launcher activity
with the payload fields (`pushSendId`, `deviceId`, `clickToken`, `eventsUrl`,
`url`) as intent extras. Verify notification tap
handling, deep-link routing, and delivered/clicked reporting. Rotate the FCM
token and confirm the second registration updates the existing device instead
of creating an uncontrolled duplicate.

## Provider failure checks

After the happy path works, test these failure cases in staging:

* Replace APNs or FCM credentials with an invalid key and confirm sends fail
  with a useful credential error.
* Uninstall the app or invalidate a browser subscription and confirm the device
  becomes inactive after provider rejection.
* Stop and restart the worker while a send is queued. Confirm an accepted
  device is not sent the same push again on retry.
* Remove the device and confirm it is excluded from the next campaign.


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