Hello,
I'm using Apple Wallet passes with a custom backend for distributing and updating them, as described in the documentation (https://developer.apple.com/documentation/walletpasses).
I'm sometimes seeing a behaviour where the device does not download an updated pass even though the push notification for informing about the changes has been successfully sent (I've received a success response from APNs).
APNs documentation says that it should retry sending the notification if the device is not reachable, but in the cases I'm describing here, the request from the device to fetch the updated pass never arrives. I don't have the apns-expiration header set. Also, I've checked the load balancer and firewall logs, etc. and there are no traces of the requests.
Any thoughts on what might be the issue here? Or how to debug this further?
Notifications
RSS for tagLearn about the technical aspects of notification delivery on device, including notification types, priorities, and notification center management.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Is it possible to display a live activity on the lock-screen without a dynamic island? Or at least without expanding the dynamic island more than just for a small icon?
struct SomeWidgetLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: SomeAttributes.self) { context in
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
// Seems to be mandatory, any way around it?
}
} compactLeading: {
} compactTrailing: {
} minimal: {
}
}
I couldn't quite find a way.
Thank you
I noticed the time sensitive entitlement says it's only for iOS and macOS. But without the entitlement, the time sensitive toggle doesn't show in my app's notification settings on visionOS.
When I archive my visionOS app for App Store Connect, the entitlement seems to be taken out as it doesn't show in my entitlement list for the build in App Store Connect.
I'm confused at this point if the entitlement is really necessary, since it seems to be needed to debug on the simulator at least. I don't have a physical device to test it on unfortunately.
Hello,
I am developing a calling service using CallKit and VOIP push.
I have occasionally encountered a strange issue.
The issue is that VOIP permanently fails to receive calls.
I was previously informed that even if the device is blocked, it can receive calls again after 24 hours.
Also, when I checked the device logic, it complied with the policy requirements set by Apple, including correctly calling CallKit's reportNewIncomingCall method.
Once the issue occurs, no matter how many times I try, VOIP does not receive calls, and neither a device reboot nor checking the Device Console Log shows any logs related to CallKit or VOIP.
I suspect this might be an issue with the VOIP token, and I believe that the only way to get a new one is to reinstall the app. Is that correct?
Of course, after reinstalling, it works fine again, but this is very inconvenient. I don't think this is the right solution.
Is there anyone who can share their insights on this issue?
Thank you.
We are observing unexpected behavior in Apple Push Notification Service (APNS) delivery and would appreciate clarification and guidance. Below is a detailed
breakdown of the scenario and related questions.
Abbreviations:
APNP – Apple Push Notification Provider
APNS – Apple Push Notification Service
Scenario:
User1 is registered on iOS device1.
Flight Mode is enabled on iOS device1.
User2 initiates a call to User1 (Time t = 0 sec).
User2 cancels the outgoing call after 5 seconds (Time t = 5 sec).
Flight Mode is disabled on iOS device1 after 20 seconds (Time t = 25 sec).
Observation:
iOS device1 displays an incoming call notification (CallKit UI) after flight mode is turned off, despite the call being cancelled by User2.
This notification disappears automatically after approximately 8–10 seconds.
Logic Flow:
At time t = 0, our APNP sends a VoIP push (priority) to APNS for the incoming call.
Since device1 is in flight mode, APNS cannot deliver the push.
At t = 25 sec, after flight mode is turned off, APNS delivers the cached VoIP push to device1.
The app takes ~5 seconds to initialize (CSDK setup, SIP registration, etc.).
It eventually receives a SIP NOTIFY with state="full" and empty dialog info (indicating no active call).
Consequently, the CallKit incoming call is removed after ~8 seconds.
Questions:
→ We set the apns-expiration header to 0, expecting that the VoIP push would not be delivered if the device was unreachable when the push was sent. However, APNS still delivers the push 20–30 seconds later, once the device is back online.
Q. Why is the apns-expiration header not respected in this case?
→ Upon receiving the VoIP push, we require ~10–12 seconds to determine if a visible CallKit notification is still relevant (e.g., by completing SIP registration and checking for active dialogs).
Q. Is it acceptable, per Apple guidelines, to intentionally delay showing the CallKit UI (incoming call) for 10–15 seconds after receiving the VoIP push?
→ Apple documentation states that the priority VoIP push channel should be used only for notifying incoming calls, while regular (non-VoIP) pushes should be used for other updates, including call cancellations.
Q. What is the rationale behind discouraging the use of the priority VoIP push channel for call cancellation events? In some cases, immediate cancellation notification is as critical as the initial incoming call. Would Apple consider it acceptable to occasionally use the priority VoIP channel for rare call-cancellation scenarios without risking throttling or suspension?
→ In our implementation, we send an incoming call notification via the priority VoIP channel. Shortly after, we send a call cancellation notification on the regular push channel, marked with "content-available": 1. We expect this regular push to wake the app (triggering application:didReceiveRemoteNotification:fetchCompletionHandler:), but in practice the app never wakes, and our debug logs inside that delegate method never appear.
Q. Under what exact conditions does a "content-available": 1 regular push fail to wake the app when it follows a VoIP push? Are there additional requirements (e.g., background modes, rate limits, power optimizations) that could prevent the delegate from being called?
→ According to Apple documentation: “APNs stores only one notification per bundle ID. When multiple notifications are sent to the same device for the same bundle ID, APNs keeps only the latest one.” However, in our tests: If a device is offline when APNs receives both: (a) a priority VoIP push for an incoming call, (b) a regular push for call cancellation (same bundle ID), Upon the device reconnecting, APNs still delivers the earlier VoIP push, instead of discarding it and delivering only the most recent (cancellation) notification.
Q. Why doesn’t APNs replace the queued VoIP push with the newer regular push when both share the same bundle ID? Is this expected behavior due to channel type differences (VoIP vs. regular), or is there a way to ensure that the latest notification (even if regular) supersedes the earlier VoIP push?
We’d appreciate your input or recommendations on handling such delayed pushes and any best practices for VoIP push expiration handling and call UI timing.
Problem
We have successfully set up push notifications using Apple APN service, that is push notifications work when using a token generated using the JSON Web Token Generator in the Push Notification console. However, we get an "InvalidProviderToken" error when creating using our own token using the following code.
The Key and TeamID is definitely correct (obviously, censored in the below code). When pasting our token in the JSON Web Token Validator in the Push Notification console we get the error „Invalid signing key“. We merely pasted our secret key in our setNewTokenIfNeeded code, separated on four lines using the “““ style.
Does anyone know why this error happens? Given that it works when we upload our .p8 file to the JSON Web Token Generator and we simply paste the text of this file (excluding the lines with "-----BEGIN/END PRIVATE KEY-----") I guess our secret key is correct?
Code to generate token
fileprivate var currentToken: String?
fileprivate var currentTokenCreateTime: Date?
fileprivate func setNewTokenIfNeeded() {
// Ensure, token is at least 20 minutes but at most 60 minutes old
if let currentTokenCreateTime = currentTokenCreateTime {
let ageOfTokenInSeconds = abs(Int(currentTokenCreateTime.timeIntervalSinceNow))
NSLog("Age of token: \(Int(ageOfTokenInSeconds / 60)) minutes.")
if ageOfTokenInSeconds <= 20 * 60 { return }
}
// Generate new token
NSLog("Renewing token.")
let secret = """
ABCABCABCABCABCABCABCABCABCABCABCABC+ABCABC+ABCABCABC+ABCABCAB/+
ABCABCABCABCABCABCABCABCABCABCABCABC+ABCABC+ABCABCABC+ABCABCAB/+
ABCABCABCABCABCABCABCABCABCABCABCABC+ABCABC+ABCABCABC+ABCABCAB/+
ABCABCAB
"""
let privateKey = SymmetricKey(data: Data(secret.utf8))
let headerJSONData = try! JSONEncoder().encode(Header())
let headerBase64String = headerJSONData.urlSafeBase64EncodedString()
let payloadJSONData = try! JSONEncoder().encode(Payload())
let payloadBase64String = payloadJSONData.urlSafeBase64EncodedString()
let toSign = Data((headerBase64String + "." + payloadBase64String).utf8)
let signature = HMAC<SHA256>.authenticationCode(for: toSign, using: privateKey)
let signatureBase64String = Data(signature).urlSafeBase64EncodedString()
let token = [headerBase64String, payloadBase64String, signatureBase64String].joined(separator: ".")
currentToken = token
currentTokenCreateTime = Date()
}
fileprivate struct Header: Encodable {
let alg = "ES256"
let kid: String = "ABCABCABC" // Key (censored here)
}
fileprivate struct Payload: Encodable {
let iss: String = "ABCABCABC" // Team-ID (censored here)
let iat: Int = Int(Date().timeIntervalSince1970)
}
extension Data {
func urlSafeBase64EncodedString() -> String {
return base64EncodedString()
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
}
Code to send the push notification
func SendPushNotification(category: ConversationCategory,
conversationID: UUID,
title: String,
subTitle: String?,
body: String,
devicesToSendTo: [String]) {
// Für alle Felder s. https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification
let payload = [
"aps": [
"alert": [
"title": title,
"subtitle" : subTitle ?? "",
"body": body
],
"category" : category.rawValue,
"mutable-content": 1
],
"conversationID": conversationID.uuidString
] as [String : Any]
// Ggf. Token setzen
setNewTokenIfNeeded()
guard let currentToken = currentToken else {
NSLog("Token not initialized.")
return
}
NSLog(currentToken)
// Notification an alle angegebenen Devices schicken
let bundleID = "com.TEAMID.APPNAME"
for curDeviceID in devicesToSendTo {
NSLog("Sending push notification to device with ID \(curDeviceID).")
let apnServerURL = "https://api.sandbox.push.apple.com:443/3/device/\(curDeviceID)"
var request = URLRequest(url: URL(string: apnServerURL)!)
request.httpMethod = "POST"
request.allHTTPHeaderFields = [
"authorization": "bearer " + currentToken,
"apns-id": UUID().uuidString,
"apns-topic": bundleID,
"apns-priority": "10",
"apns-expiration": "0"
]
request.httpBody = try! JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted)
URLSession(configuration: .ephemeral).dataTask(with: request) { data, response, error in
if let error = error {
NSLog(error.localizedDescription)
}
if let data = data {
NSLog(String(data: data, encoding: .utf8)!)
}
}.resume()
}
}
On a similar note, some people seem to encounter this error when using the prettyPrinted option for the JSON serialization (i.e., in request.httpBody = try! JSONSerialization.data(withJSONObject: payload, options: .prettyPrinted). Could this be the culprit, given our secret key contains „/„ and „+“?
Many thanks!
I have converted a large part of the data, but only 5% of the data was successfully converted. The failed devicetoken shows "bad devicetoken" when accessing APNS. Here are examples of failed conversions devicetoken. Is there any official documentation for this part?
DeviceToken Orgin \xc2\xa1\xcb\x9cr\xc3\x81\xe2\x80\x9e\x01b\xc3\xbce1pf\t\xc2\xa7\xc3\x82v}\xc3\xa1\xc3\x9a:?\r\n\xc3\xa5\xc6\x92\xc3\xb7y\xc3\x9e\xe2\x80\x9c\xc3\x89r
self.pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
self.pushRegistry.delegate = self;
self.pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
//处理接收到的VoIP推送
(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void(^)(void))completion
then we send message from our server or from apple's cloud service: https://icloud.developer.apple.com/dashboard/notifications website services:
when app is in foreground,withCompletionHandler wil be called correctly,but when app is in background or has killed ,withCompletionHandler not be called!!!
the background fetch、voice over ip is checked in signing & capabilities tabs
why?why?why?why?why?why?why?why?why?
Hello,
I am writing this because the behavior of the App Store Server Notification that our server receives is problematic in the Sandbox environment.
I have two questions in total.
When purchasing a Free Trial subscription, after receiving the SUBSCRIBED / INITAL_BUY Notification, DID_RENEW should be sent when it expires, but DID_FAIL_TO_RENEW/GRACE_PERIOD is sent.
The EXPIRE Notification is sent after the subscription expires or DID_CHANGE_RENEWAL_STATUS/AUTO_RENEW_DISABLED is sent, but it does not arrive.
The first problem is that I recently heard that automatic payments after a free trial require the user's consent via email. Is this the reason?
If so, I am curious about how I can test it in the Sandbox environment.
Is the second problem a bug?
Topic:
App & System Services
SubTopic:
Notifications
Tags:
Subscriptions
In-App Purchase
App Store Server Notifications
We've had reports that since upgrading to iOS 18.1.1, wallet pass notifications (on the lock screen) now display "Nearby" instead of the Departure time,. Has anyone else experienced this issue? There doesn't seem to be any documentation around it.
Thanks
You are probably aware of the upcoming root certificate change for any servers you might have that you use to send push notifications by connection to APNs.
If you are not, here is the announcement.
We have been getting some questions about this, and understand not everyone is familiar with their server setup.
First, we would like to clarify that this is only a change to your server's certificate trust store. You do not need to update anything else, like your APNs push certificates, the build certificates and provisioning profiles for your team/app, and so on. All you need to do is to install the mentioned new root certificate to your push server's trust store.
If you are using a 3rd party push provider, it is them who will need to handle their servers. But you may want to double check with them nevertheless.
If you are managing your own push servers that connect to APNs directly, then it is your responsibility to download and install the root certificate mentioned in the above link on your server(s).
Unfortunately we cannot provide specific instructions on how to install this root certificate on every kind of server out there. Each server operating system/push server software will have different ways these root certificates are installed, which is out of scope of our support abilities.
If you are not sure how to do this, I would recommend you seek help for this from your server-side developers or server admins.
Or, if you don't have access to such resources, you can ask the support channels for your system the question: How do I install a root certificate?
We have setup a test server at 17.188.143.34:443 that you can use to try and send pushes to test whether your new root certificate is correctly installed.
An alternative way to test this would be, from a terminal prompt:
openssl s_client -connect 17.188.143.34:443 -servername api.sandbox.push.apple.com -verifyCAfile USERTrustRSACertificationAuthority.crt -showcerts
Change the parameter to the -verifyCAfile argument to point to your trust store, and it should allow you to validate
Sample return results would be:
Connecting to 17.188.143.34
CONNECTED(00000003)
depth=2 C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
verify return:1
depth=1 CN=Apple Public Server RSA CA 11 - G1, O=Apple Inc., ST=California, C=US
verify return:1
depth=0 C=US, ST=California, O=Apple Inc., CN=api.sandbox.push.apple.com
verify return:1
Argun Tekant /
DTS Engineer /
Core Technologies
Topic:
App & System Services
SubTopic:
Notifications
Tags:
APNS
User Notifications
PushKit
Push To Talk
Discrepancy between App Store Server API `expiresDate` and iOS Settings subscription expiration date
I am developing an iOS app that uses App Store Server API (v2) for auto-renewable subscriptions.
I noticed a discrepancy between the expiration date returned by the API and the date displayed in iPhone Settings > Subscriptions:
App Store Server API expiresDate: 2025-09-12T12:10:25 (KST)
iOS Settings > Subscriptions: 2025-09-11 (one day earlier)
My understanding:
The API’s expiresDate is the precise UTC timestamp.
The Settings UI might display the "last full calendar day" for UX purposes.
Questions:
Is this behavior (UI showing one day earlier) an intentional Apple policy?
If so, is there any official documentation or guideline explaining this behavior?
Should developers always rely on the API’s expiresDate for subscription state management?
This discrepancy is confusing for both developers and end users, so any clarification or official reference would be greatly appreciated.
Topic:
App & System Services
SubTopic:
Notifications
I need to decode a Base64-encoded receipt from an In-App Purchase and extract the transaction ID from it. However, I want to avoid using the verifyReceipt endpoint since it is deprecated.
Can anyone guide me on how to achieve this manually? Are there any specific libraries, steps, or code samples I should follow to parse the receipt data and retrieve the transaction ID?
Any help or insights would be greatly appreciated!
Topic:
App & System Services
SubTopic:
Notifications
Tags:
Subscriptions
In-App Purchase
App Store Server Notifications
App Store Server API
We're trying to add simple notifications to our CarPlay integration that should open certain template when pressed, but the issue is that when pressing this notification on CarPlay screen nothing is invoked in the code (presumably didReceive should be invoked). All works fine with the same notification but pressed on the iPhone screen - didReceive is invoked properly. How should I handle the action when push notification is pressed on CarPlay screen?
Hi everyone,
We're experiencing an issue with our Flutter app that uses PushKit, CallKit, and Janus for handling VoIP calls. Everything works fine when the app is in the foreground, but when the app is in the background or completely closed (terminated state), the behavior is inconsistent:
Sometimes, incoming calls are received as expected.
Other times, the app does nothing, and the call is not delivered at all.
Upon checking the console logs, we noticed that our app is being canceled (terminated by the system), which seems to be the reason why calls are not coming through. This happens randomly, making it difficult to reproduce consistently.
Additional Details:
The app is configured to handle VoIP notifications correctly.
We are using PushKit to wake up the app and trigger CallKit for the incoming call UI.
When the app is active, calls are handled correctly via Janus WebRTC signaling.
We have verified that background modes for VoIP are enabled in the Info.plist.
We suspect that iOS may be aggressively killing the app in the background, preventing incoming call notifications from reaching it.
Questions:
Has anyone experienced similar behavior with PushKit + CallKit on recent iOS versions?
Could iOS be terminating the app due to background execution policies?
Are there recommended best practices to ensure reliable delivery of VoIP notifications when the app is closed?
Any insights or suggestions would be greatly appreciated!
Thanks!
Addional Information:
this is the cancellation information at console: Received incoming message on topic hiperme.app at priority 10
por omisión 17:10:18.462084-0300 dasd CANCELED: com.apple.pushLaunch.hiperme.app:E8BACD at priority 10
@App Store Commerce Engineer hi, have you already implement something for handle server notification if user buy non consumable purchases product, how my server should know if user boutght something ?
Topic:
App & System Services
SubTopic:
Notifications
Hi Apple team and fellow developers,
We previously had Location Push Service Extension enabled and working in production. After transferring the app to a new Apple Developer team, the production App ID was transferred, but the Location Push entitlement was not retained.
We've also created a new App ID for development, and now need Location Push access enabled for both the transferred production ID and the new development ID.
We’ve already submitted the Location Push Access form with all relevant details.
Unfortunately, the App Transfer documentation didn’t make it clear that Location Push access would be lost, and now we’re blocked from making new builds — even for the existing production app.
❓ Questions:
Is it possible to re-enable Location Push for a transferred App ID?
What’s the expected timeline for entitlement approval?
Can Apple staff confirm the request status or let us know if any further action is needed?
Thanks in advance — this entitlement is critical for our app’s functionality and release pipeline.
Best,
Aidar
Topic:
App & System Services
SubTopic:
Notifications
Tags:
APNS
Developer Tools
Maps and Location
Developer Program
Hi Apple team,
We’re shipping a Live Caller ID Lookup extension on iOS 18 and have a question about the automatic refresh of configuration/PIR parameters.
Questions
1. Is there any documented interval/TTL (min/max) for the system’s automatic refresh of /config and PIR parameters, or is it entirely opportunistic (battery/network/usage)? I can’t find a cadence in the IdentityLookup docs.
2. Does iOS honor server cache headers (e.g., Cache-Control/Expires) to influence when it re-fetches?
3. Which events also trigger a refresh (enable/disable in Settings, OS/app update, device reboot, token/epoch change)?
4. Are there rate limits or best-practice limits for calling refreshExtensionContext and refreshPIRParameters?
Topic:
App & System Services
SubTopic:
Notifications
Tags:
Extensions
SMS and Call Reporting
CallKit
I’m using iOS 26 beta 9 on my iPhone 15 Plus. When I receive a call from a contact with multiple phone numbers, the call history does not clearly show which specific number was used to call me. Why? How to fix this issue?
Topic:
App & System Services
SubTopic:
Notifications
Team-scoped keys introduce the ability to restrict your token authentication keys to either development or production environments. Topic-specific keys in addition to environment isolation allow you to associate each key with a specific Bundle ID streamlining key management.
For detailed instructions on accessing these features, read our updated documentation on establishing a token-based connection to APNs.