---
source_url: https://www.pubnub.com/docs/general/resources/migration-guides/apns2-migration-guide
title: APNs2 Migration Guide
updated_at: 2026-05-29T11:09:27.328Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# APNs2 Migration Guide

PubNub's [Mobile Push Notifications](https://www.pubnub.com/docs/general/push/send) gateway bridges native message publishing with third-party push notification services including Apple Push Notification service (APNs) and Firebase Cloud Messaging (FCM).

Apple ended support for the legacy binary APNs protocol on **March 31, 2021** (see the [Apple announcement](https://developer.apple.com/news/?id=c88acm2b)). You now use the HTTP/2 APIs. If you use PubNub to deliver mobile push notifications to Apple devices, your users aren't impacted.

PubNub already updated our infrastructure. If your application uses APNs1 certificates with PubNub, we continue to process your requests. We recommend migrating to APNs2. This guide shows how to complete the migration.

:::note Applicable to APNs1 only
This guide is only applicable to existing customers using APNs1 certificates. If you already use APNs2 token-based mobile push notifications, no action is required.
:::

## What's new in APNs2

PubNub supports PushKit APNs and VoIP mobile push notifications with APNs2. The service uses a token signing key from your account to sign requests to Apple's HTTP/2 APIs.

Support for APNs2 comes with the following changes:

* New data model for tracking Apple push configuration information for keysets. To use this, you must reconfigure your keys.
* New device registration API. To use this, you must update your client applications with the new SDK API methods.
* Updated payload structure. To use Apple's HTTP/2 push API, you must either update all applications that have push-related publishes, or create a PubNub Function to augment the data with the new structure.

## Migration steps

Follow these steps to migrate to APNs2.

### Step 1: Configure APNs2 settings on your key

On the [Admin Portal](https://admin.pubnub.com), open Key Options to configure APNs2 on your keys. Keys support dual mode. You can specify both an APNs1 certificate and an APNs2 token on the same key. You can also create a new key. New keys are automatically set to work with APNs2.

If your keys don't show APNs2 token upload settings, contact [PubNub Support](https://support.pubnub.com/).

#### Old APNs1 settings

Your key should already be set up with a certificate for APNs1 mobile push notifications. You don't need to change this configuration while you transition to the new service.

![Admin Portal: existing APNs1 certificate configuration for a keyset](https://www.pubnub.com/assets/images/admin_portal_existing_apns_config-d7b31e6c23d124802611dd2d58fa460f.png)

#### New APNs2 settings

Follow these steps to configure APNs2 settings on your key:

1. Log in to your Apple Developer account and obtain a valid authentication token signing key (.p8 file extension). Refer to the Apple Developer documentation for more information on how to register your app and obtain a signing key.
2. On the Admin Portal, go to the Mobile Push Notifications section on the Key Options page.
3. Select the APNs2 tab and click Upload Token File to upload the authentication token signing key. The remaining fields are populated automatically.

### Step 2: Add new channel registrations for devices

Add channel registrations so devices use APNs2 notifications. Upgrade to the latest SDK version. Use the code sample to add the `environment` and `topic` parameters when you add a device to one or more channels. Also set `pushGateway` to `apns2` so the device uses the APNs2 gateway. If you perform this operation on a server, update your server code.

:::note SDK versions
Make sure your SDK supports APNs2. For JavaScript, you need SDK v4.27.3 or higher; for Swift, v2.3.0 or higher; and for Objective-C, v4.12.0 or higher. Earlier versions don't support APNs2. If you're using one of our [other SDKs](https://www.pubnub.com/docs/sdks), check the SDK's changelog.
:::

#### Old APNs1 methods

##### JavaScript

```javascript
pubnub.push.addChannels({
        channels: ['ch1', 'ch2'],
        device: 'deviceToken',
        pushGateway: 'apns'
    },
    function(status) {
        if (status.error) {
            console.log("operation failed w/ error:", status);
        } else {
            console.log("operation done!")
        }
    }
);
```

##### Swift

```swift
pubnub.addPushChannelRegistrations(
  ["channelSwift"],
  for: deviceToken
) { result in
  switch result {
  case let .success(channels):
    print("The list of channels added for push: \(channels)")
  case let .failure(error):
    print("Failed Push Modification Response: \(error.localizedDescription)")
  }
}
```

##### Objective-C

```objectivec
[self.client addPushNotificationsOnChannels:@[@"wwdc",@"google.io"]
                        withDevicePushToken:self.devicePushToken
                                   pushType:PNAPNSPush
                              andCompletion:^(PNAcknowledgmentStatus *status) {
    if (!status.isError) {
    } else {
    }
}];
```

#### New APNs2 methods

##### JavaScript

```javascript
pubnub.push.addChannels(
  {
    channels: ['ch1', 'ch2'],
    device: 'deviceToken',
    pushGateway: 'apns2',
    environment: 'production', // required for APNs2
    topic: 'com.mycompany.mybundleid' // required for APNs2
  },
  function(status) {
    console.log(status);
  }
);
```

##### Swift

```swift
pubnub.modifyAPNSDevicesOnChannels(
  byRemoving: [],
  thenAdding: ["ch1", "ch2"],
  device: deviceToken,
  on: "com.mycompany.mybundleid",
  environment: .production
 ) { result in
  switch result {
    case let .success(response):
      print("Successful Push Modification Response: \(response)")

    case let .failure(error):
      print("Failed Push List Response: \(error.localizedDescription)")
  }
}
```

##### Objective-C

```objectivec
[self.client addPushNotificationsOnChannels:@[@"wwdc",@"google.io"]
                        withDevicePushToken:self.devicePushToken
                                   pushType:PNAPNS2Push
                                environment:PNAPNSProduction
                                      topic:@"com.my-application.bundle"
                              andCompletion:^(PNAcknowledgmentStatus *status) {
    if (!status.isError) {
    } else {
    }
}];
```

### Step 3: Verify the new registrations

After you add device registrations, confirm the APNs2 registrations by listing the channels for the device’s device token (`deviceToken`). The following code returns the list of channels.

#### JavaScript

```javascript
pubnub.push.listChannels(
  {
    device: deviceToken,
    pushGateway: 'apns2',
    topic: 'com.mycompany.mybundleid',
    environment: 'production'
  },
  function(status) {
    console.log(status);
  }
);
```

#### Swift

```swift
pubnub.listAPNSPushChannelRegistrations(for: deviceToken, on: "com.app.bundle", environment: .production) { result in
  switch result {
  case let .success(response):
    print("Successful Push List Response: \(response)")
  case let .failure(error):
    print("Failed Push List Response: \(error.localizedDescription)")
  }
}
```

#### Objective-C

```objectivec
[self.client pushNotificationEnabledChannelsForDeviceWithPushToken:self.devicePushToken
                         pushType:PNAPNS2Push
                      environment:PNAPNSDevelopment
                            topic:@"com.my-application.bundle"
                    andCompletion:^(PNAPNSEnabledChannelsResult *result, PNErrorStatus *status)
                    {
    if (!status.isError) {
        // Handle downloaded list of channels using: result.data.channels
    } else {
    }
}];
```

### Step 4: Add push payload to messages

APNs2 requires additional fields in the message payload. PubNub can deliver both APNs1 and APNs2 notifications with the same message. Include the required APNs2 fields in the message. APNs1 payloads go to APNs1 devices on the channel, and APNs2 payloads go to APNs2 devices on the channel.

To support APNs2, structure your payload as follows. You don't need to change the underlying `publish` method. The method sends the message to PubNub with the push payload.

The `pn_apns` payload consists of:

* Two objects: [aps](#aps) and [pn_push](#pn_push)
* Two additional parameters: [pn_debug](#additional-parameters) and [pn_ttl](#additional-parameters)

```json
{
  "pn_apns": {
    "aps": {
        // necessary items
    },
    "pn_push": {
       // necessary items
    },
  "pn_debug": true,
  "pn_ttl": 60
}
```

#### aps

The `aps` dictionary contains the keys Apple uses to deliver the notification to the user's device. The keys specify the type of interactions the system uses when alerting the user. Refer to the [Apple Developer documentation](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification) for more information.

#### pn_push

The `pn_push` object contains the configuration of the push message.

| Key | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `push_type` | String | No | `alert` | Available values: `alert`, `background`, `voip`, `complication`, `fileprovider`, or `mdm`. Refer to `apns_push_type` in the [Apple Developer documentation](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns) for more information. |
| `auth_method` | String | No | `token` | Available values: `token`, `cert`, or `certificate` |
| `targets:environment` | String | No | `development` | Apple environment for the certificate associated with the PubNub key-set in use. Available values: `development` or `production`. |
| `targets:topic` | String | Yes |  | Bundle ID of your target application |
| `targets:excluded_devices` | [String] | No |  | A list of device tokens that should be excluded from receiving the notification. Typically, you can add your own device so you don't get a notification you publish. |
| `version` | String | Yes |  | Set to `v2`. |
| `pn_collapse_id` | String | No |  | An identifier to join multiple notifications into a single notification. |

#### Additional parameters

| Key | Type | Required | Description |
| --- | --- | --- | --- |
| `pn_debug` | boolean | No | A flag that enables publishing push debugging info to the `pndebug` channel. For more information, refer to [Mobile Push Troubleshooting](https://www.pubnub.com/docs/general/push/mobile-push-troubleshooting#debug-messages). |
| `pn_ttl` | int | No | A PubNub push property. It represents the number of seconds the notification is valid for from the time the notification is published to PubNub until the push server processes the publish. This flag only determines if PubNub forwards the notification to APNS, there is no consideration of a user device state. The default value for this parameter is 3600 seconds (1 hour). You don't have to set it if you provide [expirationDate](https://www.pubnub.com/docs/sdks/javascript/api-reference/mobile-push#push-notification-format-configuration) (used in an APNS POST request as the `apns-expiration` header value) in the push notification configuration. |

#### Old APNs1 message payload

```json
{
   "text":"hello world",
   "pn_apns":{
      "aps":{
         "alert":"hello world",
      }
   }
}
```

#### New APNs2 message payload

```json
{
   "text":"hello world",
   "pn_apns":{
      "aps":{
         "alert":"hello world"
      },
      "pn_push":[
         {
            "push_type": "alert",
            "auth_method": "token",
            "targets":[
               {
                  "environment":"production",
                  "topic":"bundle_id"
               }
            ],
            "version":"v2"
         }
      ]
   }
}
```

:::tip Push payload using Functions
If you're unable to modify the message payload on client apps you can also trigger serverless logic using [Functions](https://www.pubnub.com/docs/serverless/functions/overview). The function will add the additional APNs2 fields in the message before it is published so you don't have to update your client app. For more information, refer to the [sample Function code](https://gist.github.com/nishith-pubnub/c5b253d2a5b77db4a70fa8a2d0074ca8).
:::

###### JavaScript

```javascript
//publish on channel
pubnub.publish(
  {
    channel: 'ch1'
    message: payload
  },
  function (status, response) {
    console.log(status);
  }
);
```

###### Swift

```swift
pubnub.publish(
  channel: "ch1",
  message: payload
) { result in
  switch result {
    case let .success(response):
      print("Successful Response: \(response)")

    case let .failure(error):
      print("Failed Response: \(error.localizedDescription)")
  }
}
```

###### Objective-C

```objectivec
self.client publish:nil toChannel:channel mobilePushPayload: payloads
      withCompletion:^(PNPublishStatus *status) {
    if (!status.isError) {
    }
    else {
    }
}];
```

### Step 5: Remove old channel registrations for devices

Finally, remove old APNs1 device registrations from channels. This avoids duplicate notifications. The sample code shows how to remove device registrations from the `apns` gateway. You can perform this operation from your server instead of the client applications.

#### JavaScript

```javascript
pubnub.push.removeChannels({
        channels: ['ch1', 'ch2'],
        device: 'deviceToken',
        pushGateway: 'apns'
    },
    function(status) {
        if (status.error) {
            console.log("operation failed w/ error:", status);
        } else {
            console.log("operation done!")
        }
    }
);
```

#### Swift

```swift
pubnub.removePushChannelRegistrations(
  ["channelSwift"],
  for: deviceToken
) { result in
  switch result {
  case let .success(channels):
    print("The list of channels added for push: \(channels)")
  case let .failure(error):
    print("Failed Push Modification Response: \(error.localizedDescription)")
  }
}
```

#### Objective-C

```objectivec
[self.client removePushNotificationsFromChannels:@[@"wwdc",@"google.io"]
                        withDevicePushToken:self.devicePushToken
                                   pushType:PNAPNSPush
                              andCompletion:^(PNAcknowledgmentStatus *status) {
    if (!status.isError) {
    } else {
    }
}];
```

## Debug mobile push notifications

Inspect messages published to a `{channelName}-pndebug` channel to troubleshoot push notification issues. For example, if you publish on `ch1`, the debug channel is `ch1-pndebug`. Subscribe using the [PubNub Debug Console](https://www.pubnub.com/docs/console/) to investigate issues such as invalid device tokens or invalid push payloads. For more information, refer to [Mobile Push Troubleshooting](https://www.pubnub.com/docs/general/push/mobile-push-troubleshooting).