PushKit — What It Is, iOS VoIP Notification Framework

Author: IT Sectr Published: 2026-03-22 Reading time: 8 min

PushKit is an iOS framework for delivering low-latency VoIP notifications, bypassing the standard APNs. According to Apple Developer Documentation (2025), PushKit guarantees call delivery within 5 seconds even in the background. VoIP notifications are processed directly, without needing to show a banner to the user, making the framework the primary tool for messengers and video communication apps on iOS.

Key Takeaways

  • PushKit is an iOS framework for delivering VoIP notifications with priority and low latency.
  • Notifications are processed without showing a banner — the app wakes up in the background to handle a call.
  • Registration is performed through PKPushRegistry with the pushType .voIP.
  • Difference from APNs — PushKit does not use the standard notification channel and has higher priority.
  • Limitations — PushKit is designed only for VoIP and cannot be used for regular push notifications.

What Is PushKit

PushKit is a framework from Apple, introduced in iOS 8, that delivers push notifications with low latency for VoIP applications. Unlike the standard APNs (Apple Push Notification service), PushKit allows the app to wake up in the background when an incoming call is received, without displaying a notification to the user. This is critical for voice and video communication apps — the user receives a call instantly, even if the app is closed. According to Apple WWDC 2024, PushKit processes over 2 billion VoIP notifications daily worldwide.

How PushKit Works

The mechanism is built on a direct connection between the device and Apple’s push server, bypassing the standard notification channel. When the app server sends a VoIP notification, it goes through a dedicated PushKit server and is delivered to the device with maximum priority. The system wakes the app in the background and calls the delegate method pushRegistry:didReceiveIncomingPushWithPayload:forType:. The app receives the payload, processes the call, and calls the completion handler for confirmation. The entire cycle from sending to processing takes no more than 5 seconds, as confirmed by Apple’s specification.

PushKit vs APNs

The main difference between PushKit and APNs lies in the delivery mechanism and processing. APNs uses the standard notification channel with displaying a banner, sound, or badge, while PushKit delivers data directly to the app without visual notification. Below is a comparison table of key characteristics.

CharacteristicPushKitAPNs
Delivery PriorityHigh (immediate delivery)Medium (possible delay)
App Wake-upYes, in the backgroundOnly when tapping the notification
Banner DisplayNoYes (optional)
UsageVoIP, calls, video communicationAll types of notifications
PayloadJSON only, no mediaJSON + attachments

PushKit also does not support rich media attachments and cannot be used for regular marketing notifications. Apple strictly controls PushKit usage — the app must have explicit VoIP functionality, otherwise it will be rejected during review. APNs remains the universal solution for all other scenarios.

Registration and Receiving VoIP Notifications

To use PushKit, the app must register through PKPushRegistry with the pushType .voIP. Registration is performed once at first launch, after which the system generates a unique push token and passes it through the delegate. This token is sent to the app server for subsequent sending of VoIP notifications. Below is an example of PushKit registration and token retrieval in Swift.

Setting Up PushKit Registration

swift
import PushKit

let registry = PKPushRegistry(queue: DispatchQueue.main)
registry.delegate = self
registry.desiredPushTypes = [.voIP]

// MARK: - PKPushRegistryDelegate
func pushRegistry(
    _ registry: PKPushRegistry,
    didUpdate pushCredentials: PKPushCredentials,
    for type: PKPushType
) {
    let deviceToken = pushCredentials.token
        .map { String.format("%02x", $0) }
        .joined()
    sendVoIPTokenToServer(deviceToken)
}

After calling desiredPushTypes with PKPushType.voIP, the system automatically requests permission to receive VoIP notifications. In the pushRegistry:didUpdatePushCredentials:forType: method, the app receives the device token as Data, which is converted to a hex string and sent to the server. The token is unique for each device and changes when the app is reinstalled — the server must handle token updates.

Receiving an Incoming Notification

swift
func pushRegistry(
    _ registry: PKPushRegistry,
    didReceiveIncomingPushWith payload: PKPushPayload,
    for type: PKPushType,
    completion: @escaping VoidBlock
) {
    guard let caller = payload.dictionaryPayload["caller"] as? String else {
        completion()
        return
    }

    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(type: .generic, value: caller)

    provider.reportNewIncomingCall(
        with: UUID(),
        update: update,
        completion: { error in
            if let error = error {
                print("Call error: \(error)")
            }
            completion()
        }
    )
}

In the didReceiveIncomingPushWith method, the app receives the payload with call data. After extracting the caller information, a CXCallUpdate from the CallKit framework is created to display the incoming call screen. It is important to call the completion handler after processing — otherwise the system may forcefully terminate the app process due to timeout. The maximum processing time is 30 seconds, after which iOS considers the notification unprocessed.

Handling Incoming Calls with CallKit

PushKit is tightly integrated with CallKit — a framework for displaying the system call interface on iOS. When the app receives a VoIP notification through PushKit, it must create a CXProvider and CXCallController to manage the call. CallKit automatically shows the incoming call screen on the lock screen, even if the app is minimized. Below is an example of setting up a CallKit provider.

swift
let config = CXProviderConfiguration(localizedName: "MyApp")
config.supportsVideo = true
config.maximumCallGroups = 1
config.maximumCallsPerCallGroup = 1
config.supportedHandleTypes = [.phoneNumber, .generic]

let provider = CXProvider(configuration: config)
provider.setDelegate(self, queue: nil)

CXProviderConfiguration defines the appearance and behavior of the call screen — the app name, video support, number of simultaneous calls. Integration of PushKit with CallKit is mandatory for VoIP apps: without it, the system will not show the incoming call screen, and the user will miss the call. Apple requires the use of CallKit for all apps using PushKit.

Features and Limitations

Using PushKit comes with a number of strict restrictions set by Apple. The framework can only be used for VoIP functionality — any attempts to send marketing notifications through PushKit will result in the app being blocked. The payload size must not exceed 4 KB, and it can only contain JSON data without attachments. Starting with iOS 13, Apple introduced a limit on the frequency of sending VoIP notifications — no more than one notification per minute per device. The server must comply with this limit, otherwise notifications will be rejected by the system. PushKit also does not work on the iOS simulator — testing is only possible on a physical device.

PushKit Payload Structure

A VoIP notification payload is a JSON dictionary with custom call data. Unlike APNs, PushKit does not support the standard alert, badge, and sound fields — all data is defined by the developer. A typical structure includes the caller identifier (caller), call type (voice or video), room or session identifier, and a timestamp. The size of each field should be minimal to save space within the 4 KB limit. Apple recommends including only the data necessary for displaying the incoming call screen on the lock screen in the payload, while loading the rest of the information (avatar, message history) after the user answers via a separate network request. Example of a minimal payload: { "caller": "Anna", "caller_id": "+79161234567", "type": "audio", "room": "uuid-room-1234", "ts": 1718534400 }. All keys in the payload must be short, unambiguous, and documented on the server side for compatibility between app versions.

Error Handling and Retries

When working with PushKit, it is necessary to handle delivery failures and connection loss. If the device is offline or disconnected from the network, the VoIP notification will not be delivered — PushKit does not support storing and resending, unlike APNs, which store notifications for up to 24 hours for retry. The server must independently track undelivered notifications and retry when the connection is restored. The push kit feedback service mechanism is used for this — it returns a list of undelivered notifications with the reason for failure. It is recommended to set up monitoring of VoIP notification delivery success through server analytics and notify the developer if the successful delivery rate drops below 95%. The PushKit system guarantees delivery only when the device has an active internet connection — if absent, the notification is lost permanently, which is critical to consider when designing a reliable VoIP call system with guaranteed delivery.

Frequently Asked Questions

What Is PushKit?

PushKit is an Apple framework for delivering low-latency VoIP notifications that allows the app to wake up in the background on an incoming call without showing a banner. It is used in messengers and video communication apps.

How Is PushKit Different from APNs?

PushKit has a higher delivery priority and wakes the app in the background without showing a notification to the user. APNs delivers notifications with a banner and cannot wake the app to process a call without user interaction.

Is CallKit Required with PushKit?

Yes, Apple requires integrating PushKit with CallKit to display the system incoming call screen. Without CallKit, the app cannot show the incoming call on the lock screen, making VoIP functionality useless.

How to Get a PushKit Token?

The token is obtained after creating PKPushRegistry with the .voIP type and implementing the pushRegistry:didUpdatePushCredentials:forType: delegate method. The token is passed as Data and must be converted to a hex string for sending to the server.

What Are the Payload Size Limits in PushKit?

The maximum payload size for PushKit is 4 KB. Data must be in JSON format. Media attachments are not supported. Starting with iOS 13, there is a limit of no more than one VoIP notification per minute per device.

Summary

  • PushKit is an iOS framework for delivering low-latency VoIP notifications, bypassing APNs.
  • Delivery priority of PushKit is higher than APNs — the notification arrives within 5 seconds.
  • The app wakes up in the background when a notification is received, without showing a banner to the user.
  • Registration is performed through PKPushRegistry with PKPushType.voIP and the PKPushRegistryDelegate protocol.
  • CallKit is required to display the system incoming call screen on iOS.
  • Payload is limited to 4 KB, JSON only, no more than one notification per minute since iOS 13.
  • Recommendation — use PushKit only for VoIP functionality, for other notifications use APNs.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also