StoreKit

RSS for tag

Support in-app purchases and interactions with the App Store using StoreKit.

StoreKit Documentation

Posts under StoreKit subtopic

Post

Replies

Boosts

Views

Activity

App Store StoreKit web hooks doesn't work o=in the Sandbox env.
Hey! We're implementing In-App Purchase Subscriptions and we were able to receive "App Store Server Notifications" on our "Sandbox Server URL". But the last event we received 22 hours ago. We are able to verify transactions and finish them, but receive no webhooks. We changed nothing on our server or its configurations but the notifications stoped to come. We consulted the API (https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/history) and it says the same as we see - the last event was 22hrs ago. I checked all the advices from here as well (https://developer.apple.com/forums/thread/805806?answerId=864483022#864483022). Is there any Status page for the Store Kit Sandbox services? Was there any outage? Sincerely, Konstantin
2
2
196
Nov ’25
In iOS 26 beta3 version, the finishTransaction method is unable to remove transactions from the SKPaymentQueue, causing transactions to remain in the queue even after being processed.
We have some users who have upgraded to iOS 26 beta3. Currently, we observe that when these users make in-app purchases, our code calls [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; method, and we clearly receive the successful removal callback in the delegate method - (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray<SKPaymentTransaction *> *)transactions. However, when users click on products with the same productId again, the method - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions still returns information about previously removed transactions, preventing users from making further in-app purchases.
2
3
493
Jul ’25
StoreKit appAccountToken Not Preserved During Apple ID Email Migration
I'm encountering an issue with the App Store Server API where the appAccountToken is not preserved when users migrate their Apple ID email addresses. I've submitted Feedback Assistant ticket FB18709241 but wanted to check if anyone else has experienced this and get community input on best practices. The Issue When a user migrates their Apple ID from one email to another (e.g., from olduser@example.com to newuser@icloud.com), the App Store creates a new subscription transaction with a different originalTransactionId, but the appAccountToken is not carried forward from the original transaction. What I'm Seeing note: these values are fake When querying /inApps/v1/subscriptions/{originalTransactionId} with the either post-migration transaction ID or the pre-migration transaction ID, the API returns both transactions: Pre-migration transaction (status: 2 - inactive): originalTransactionId: "12345678910111" Contains: "appAccountToken": "abc123-def456-ghi789" Post-migration transaction (status: 1 - active): originalTransactionId: "67891011121314" Missing: appAccountToken entirely The Problem The appAccountToken is our only way to link App Store subscriptions to user accounts. Without it on the new transaction: Users lose access to premium features despite having valid subscriptions Server-side renewal notifications can't be matched to user accounts Manual support intervention is required for each affected user Questions for the Community Has anyone else encountered this issue with Apple ID migrations? What's the recommended approach for handling this scenario? Is there an alternative mechanism to maintain the subscription-to-user linkage across migrations? Questions for Apple Engineers Is this the expected behavior, or should the appAccountToken be preserved? Are there any planned improvements to handle this migration scenario? What's the best practice for developers to handle this case? Interestingly, both the old and new transaction IDs return the same JSON response from the App Store Server API, suggesting Apple maintains internal linkage between these transactions, but the appAccountToken isn't carried forward to the active transaction. Any insights or similar experiences would be greatly appreciated! Thank you!! Feedback Assistant: FB18709241
0
3
188
Jul ’25
Unknown Error Occurring During Sandbox Purchase Testing
We are experiencing an Unknown Error (error code 0) when testing purchases in the Apple Sandbox environment. The error does not occur every time, but it fails with an Unknown Error in approximately 8 out of 20 attempts. Due to this issue, our app is failing to pass Apple’s review. Issue Details This issue only occurs in the Apple Sandbox environment. After attempting a purchase, the Apple payment API returns SKPaymentTransaction Unknown Error. Returned error code: SKErrorUnknown (error.code 0). This problem is preventing us from conducting proper payment tests and getting approval from Apple. Would it be possible to receive support or any solutions for this issue?
0
2
254
Mar ’25
Not receiving Sandbox Server-to-Server Notifications for In-App Purchases (App Store Server Notifications v2)
I’m testing auto-renewable subscription purchases in the sandbox environment. When I buy a subscription package using a sandbox test user, I don’t receive any App Store Server Notifications from the sandbox. However, when I use the “Request Test Notification” option in App Store Connect, the notification is received successfully. My sandbox server notification URL is configured correctly and publicly accessible. I also call finishTransaction() after purchase, and the receipt is verified successfully with the sandbox verification endpoint. To further debug, I used the getNotificationHistory API to fetch notifications for yesterday and today (Nov 3–4, 2025). Apple’s API response does not include any notifications or transaction IDs for my today’s purchases (Nov 4, 2025) — even though I can confirm from logs that those transactions were completed and verified successfully. It looks like sandbox purchase notifications are not being sent or logged, even though test notifications work fine. Could someone from Apple please confirm if there’s currently an issue with sandbox server notifications for auto-renewable subscriptions?
8
2
410
Dec ’25
App Store Server Notifications and API Client - Toggling Sandbox vs Production Environment
The documentation mentions the following: Verify your receipt first with the production URL; then verify with the sandbox URL if you receive a 21007 status code. This approach ensures you don’t have to switch between URLs while your app is in testing, in review by App Review, or live in the App Store. This way, you can use one server environment to handle both Sandbox and Production environments. It is necessary to pass App Review. However, I'm not manually hitting these URLs - I'm using Apple's libraries. Specifically, the environment is used in SignedDataVerifier and AppStoreServerAPIClient. (I can't link to these because, for some reason, the domain apple.github.io is not allowed. The documentation for these is only found there. You can find it quickly by searching these terms and the domain.) Here is how SignedDataVerifier is being used: const verifier = new SignedDataVerifier( appleRootCertificates, APPLE_ENABLE_ONLINE_CHECKS, APPLE_ENVIRONMENT, APPLE_BUNDLE_ID, APPLE_APP_ID ) const verifiedNotification: ResponseBodyV2DecodedPayload = await verifier.verifyAndDecodeNotification(signedPayload) if (!verifiedNotification) { // Failure return } Here is how AppStoreServerAPIClient is being used: const appStoreServerAPIClient = new AppStoreServerAPIClient( SIGNING_KEY, APPLE_IAP_KEY_ID, APPLE_IAP_ISSUER_ID, APPLE_BUNDLE_ID, APPLE_ENVIRONMENT ) const statusResponse: StatusResponse = await appStoreServerAPIClient.getAllSubscriptionStatuses(originalTransactionId, [Status.ACTIVE]) In the source code for SignedDataVerifier.verifyAndDecodeNotification, I can see that it throws a VerificationException(VerificationStatus.INVALID_ENVIRONMENT) error . So for SignedDataVerifier is it as simple as wrapping my code in a try/catch and checking that the error's status code is 21007? I'm unsure about this because if you scroll to the bottom of the linked source code file, you can see the enumeration VerificationStatus, but it's unclear if this member has a value of 21007. The source code for AppStoreServerAPIClient only says that it throws an APIException if a response could not be processed, so I'm not too sure about how to handle this one.
2
2
961
Sep ’25
Unexpected 401 Unauthorized response from production endpoint when using sandbox transactionId with Get Transaction Info API
We have encountered an issue when verifying transactions using the Get Transaction Info API. We tested the behavior in both the sandbox and production environments and observed the following results. When calling the production endpoint: https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId} with a transactionId generated in the sandbox environment, the API returns HTTP 401 Unauthorized. However, based on the documentation and common understanding, we expected HTTP 404 Not Found in this case. Using the same JWT token, if we call the sandbox endpoint: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/{transactionId}, we receive HTTP 200 OK with the expected response body. We have also confirmed that the same behavior occurs when using the Get Transaction History API — it works correctly in the sandbox environment but returns 401 in production. Could you please confirm whether this behavior (receiving 401 instead of 404) is expected by design, or if it indicates a potential issue? If this is not the intended behavior, we would appreciate any guidance or instructions to resolve it. Thank you very much for your technical support. 「Get Transaction Info」APIを用いてトランザクションの検証を行ったところ、以下の問題が発生しました。 サンドボックス環境および本番環境の両方で検証を行い、次の結果を確認しています。 本番環境エンドポイント https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId} に対して サンドボックス環境で生成された transactionId を使用すると、HTTP 401 Unauthorized が返却されます。 (一般的には、この場合 404 Not Found が返る想定であると理解しています。) 同一のJWTトークン を用いて サンドボックス環境のエンドポイント https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/{transactionId} を呼び出した場合は、HTTP 200 OK が返り、期待通りのレスポンスボディを受け取ることができています。 また、同様の挙動が Get Transaction History を使用した場合にも発生することを確認しています。 サンドボックス環境では正常に動作しますが、本番環境では401が返却されます。 この挙動(401が返却されること)は仕様上想定されたものか、または何らかの問題によるものかご確認をお願いいたします。 もし想定外の挙動である場合は、解決に向けたご案内をいただけますと幸いです。 本件について、技術的なサポートをお願いいたします。 よろしくお願いいたします。
2
0
285
Nov ’25
StoreKit 2 Fails to Load Subscription Products
We are experiencing a critical issue where StoreKit 2 is returning empty products when using Product.products(for:), specifically on devices running iOS 18.4.

 This issue does not occur on iOS 18.3 or earlier.

 Steps:

 Created a subscription product (e.g. "upm1") in App Store Connect
 Confirmed the product is active, localised, and part of a valid subscription group
 Call the following Swift code using StoreKit 2:
 Task { do { let products = try await Product.products(for: ["upm1"]) print(products) } catch { print("Error: (error)") } } 4. Result: products is an empty list.

 This regression is blocking subscription testing on iOS 18.4. 

 Kindly someone please advise on a potential fix or workaround.
2
2
286
Sep ’25
Auto-renewing Subscription Updates not Arriving
This is a copy of a reply to this post. https://developer.apple.com/forums/thread/722222?page=1 I'm posting as new in the hope someone might have more up-to-date information, as I'm pulling out what little hair I have left. I'm using Storekit 2, testing in Xcode with a local Storekit config file. I have created a very minimal system to investigate this issue. I have a SwiftUI-based window using SubscriptionStoreView, and my app set up with the usual listener. I have four types of auto renewing subscription, configured in the local Storekit config file. With my app running, I subscribe to the lowest-level subscription I offer, via the SubscriptionStoreView. Notification of the inital purchase arrives, but subsequent auto-renewals do not trigger any action in my listener for Transaction.updates. They arrive as expected in the Transaction Manager. Radio silence in my listener. If I upgrade one subscription (via my SubscriptionStoreView) I see this reflected in the UI immediately, and also in the Transaction Manager, but the update that arrives in Transaction.updates refers to the old subscription, and has the isUpgraded flag set to false. Also, can anyone remind me what the grey warning triangle next to entries in the Transaction Manager means. I'm assuming it means unfinished, as that's what the sidebar indicates. Can the testing system really be this broken, or am I wildly off the mark? Unless I'm doing something fundamentally wrong this all seems extremely flakey, but happy to be proved wrong. I find this all rather unsettling if I can't test reliably, and am concerned that I my app may end up in this situation if I use storekit 2: https://stackoverflow.com/questions/73530849/storekit-renewal-transactions-missing-in-transaction-all-or-transaction-updates
10
2
2.2k
Feb ’26
Cannot Cancel Sandbox Subscription
I did an in app purchase in my development app and now I cannot get rid of it. It is a "monthly" subscription that seems to renew every 1 day. I can see the subscription when I go to settings then tap on Subscriptions. Then I tap the item and choose "Cancel Subscription", revealing a new modal sheet saying "Confirm Cancellation". When I "Confirm", I get the popup: "Your request is temporarily unable to be processed, please try again later". However, this is anything BUT temporary, has gone on for a couple weeks now. As such, I am unable to test subscriptions in my development app. I've tried logging out, restarting, different devices, etc. The phone is logged in under my primary user account, and I may not have been logged into sandbox email when I did the purchase. Can someone forcibly remove it for me?
2
2
700
Nov ’25
Why does a purchase result in success unverified?
A purchase can result in success with verificationResult .unverified. Is there a list of reasons for which the transaction might be unverified and how should i handle it in my app? From my understanding, a successful unverified transaction means the user has already paid for the purchase. So, do i just ignore the unverified transaction or do i provide content to the user anyways?
1
2
126
Jul ’25
Unable to enable eligibility for External Purchase Link APIs — seeking clarification
Hello, I am currently implementing External Purchase Link and External Purchase Custom Link and am encountering an issue where both ExternalPurchaseLink.canOpen and ExternalPurchaseCustomLink.isEligible always return false under all test conditions. I would like to confirm whether my setup is missing any required steps or whether this behavior is expected. Below are the details of my current environment and configuration: 🔧 1. Development Environment Xcode: 16.3, 16.4, 26.0 beta 4 Devices: iPhone running iOS 26.2 beta iPhone running iOS 16.7.12 macOS 15.5 (real device testing) Simulator iOS 18.0 Build Type: Local development build using a Developer Provisioning Profile Sandbox account signed in during testing 🔑 2. Entitlements (Developer site & Xcode) In Certificates → Identifiers → App ID, both capabilities are enabled: StoreKit External Purchase StoreKit External Purchase Link The .entitlements file in Xcode includes: com.apple.developer.storekit.external-purchase = YES com.apple.developer.storekit.external-purchase-link = YES The Provisioning Profile also contains both entitlements (confirmed via codesign -d --entitlements :-). 📄 3. Info.plist Configuration Both keys are configured with correct region codes according to documentation: SKExternalPurchase SKExternalPurchaseCustomLinkRegions 🌍 4. Test Storefront Device storefront verified as United States (US) or Portugal (PT) (US = target region for External Purchase Link, PT = EU region) But despite all the above configuration, both API calls consistently return false: ExternalPurchaseLink.canOpen // false ExternalPurchaseCustomLink.isEligible // false So I cannot proceed to testing the remaining flow (token retrieval, link opening, etc.) ------ Questions ------ ❓ Q1) Local Development Build Limitation Is it expected behavior that Developer-signed local builds always return canOpen = false / isEligible = false for External Purchase Link & Custom Link? Is there a technical or policy restriction that prevents eligibility in local dev builds? ❓ Q2) App Store Connect Configuration Requirement Are there mandatory App Store Connect settings (such as external purchase URLs, support URL, disclosures, or country configuration) that must be enabled before eligibility becomes true? Currently, no External Purchase Link or Custom Link menu is visible in my App Store Connect app settings. Is this menu only available after certain approvals or under specific conditions? ❓ Q3) TestFlight Requirement Do External Purchase Link and Custom Link only return eligibility = true on: TestFlight builds, or Distribution-signed builds? Or should eligibility also work on developer builds? Formal confirmation would be helpful. ❓ Q4) Developer Account Type Limitation We are using an Individual Developer Account (not Organization). Can Individual accounts fully request, test, and ship apps using: External Purchase Link External Purchase Custom Link Or are there limitations on account type? 🙏 Request We have completed all documented setup steps (Entitlements → Provisioning → Info.plist), but eligibility remains false, blocking feature validation. Please clarify which of the following is the cause: Local development builds do not support eligibility Missing App Store Connect configuration (not visible to us) Account type restriction Region rollout or entitlement approval requirement Any additional setup not documented publicly Thank you for your assistance.
2
1
225
1w
Unauthorized for Advanced Commerce API Purchase
Hi! My product SKU has been approved for Advanced Commerce API. I successfully receive a purchase pop-up with the correct information. However, I am still having issues with completing the purchase. I always receive Unauthorize error when I confirm the purchase (subscription in my case; see the screenshot). I am using the node.js server library to sign the request. I made sure that the account is a valid account enabled for Sandbox. Logs unfortunately don't indicate any further detail. Thanks for your advice! We've been stuck on this for a while now and would appreciate your help. Marek
6
2
307
Jul ’25
DID_FAIL_TO_RENEW Notification with a null gracePeriodExpiresDate
We are seeking clarification on the behavior of App Store Server Notifications V2. Summary In our production environment, we received a notification with notificationType: DID_FAIL_TO_RENEW and subtype: GRACE_PERIOD. However, the gracePeriodExpiresDate field in the payload was null. We understand this notification indicates that a user's subscription has entered a grace period. The null value for its expiration date is unexpected, and we are looking for an official explanation of this behavior and the correct way to handle it. The Scenario Here are the details of the notification we received: Notification Type: DID_FAIL_TO_RENEW Notification Subtype: GRACE_PERIOD Environment: Production Upon decoding the signedRenewalInfo JWS from the responseBodyV2, we found that the gracePeriodExpiresDate field inside the JWSRenewalInfoDecodedPayload was null. The notificationUUID for this event was in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Our Implementation and its Impact Our backend is designed to ensure service continuity during a grace period, as recommended in the documentation. Current Logic: Receive the DID_FAIL_TO_RENEW / GRACE_PERIOD notification. Extract the gracePeriodExpiresDate. Extend the user's subscription expiration date in our database to match this date. Because the gracePeriodExpiresDate was null in this case, our logic failed, creating a risk of service interruption for the user. Context and Investigation We have performed the following checks: App Store Connect Settings: We have confirmed that Billing Grace Period is enabled for the relevant subscription group. Sandbox Environment: We have been unable to reproduce this scenario in the Sandbox. User Context: We believe the user in this case was experiencing a failed payment when attempting to renew for the first time after a free trial period. Questions To ensure we handle this scenario correctly, we would appreciate clarification on the following points: Conditions for Null: Under what specific conditions does a DID_FAIL_TO_RENEW notification with a GRACE_PERIOD subtype contain a null gracePeriodExpiresDate? Expected Behavior: Is this null value an expected behavior for certain scenarios, such as the first failed renewal after a free trial? Best Practice: If this is an expected behavior, what is the correct way to handle it? How should our backend interpret a null gracePeriodExpiresDate to ensure service continuity for the user?
2
2
208
Jul ’25
【iOS18.2~18.3.2 bug】After switching sandbox accounts in Settings, the value of SKStorefront.countryCode is not synchronized
Problem Description: 1、I have two sandbox accounts from different countries. Account A is from Mainland China (CHN), and Account B is from the United States (USA). When I switch the sandbox account from Account A (CHN) to Account B (USA) in the system settings and restart the app, the value of SKPaymentQueue.defaultQueue.storefront.countryCode always returns "CHN" instead of the expected "USA". 2、This issue only occurs on iOS 18.2 and above. 3、On the same device running iOS 17.5.1, the behavior is correct. However, after upgrading the system to iOS 18.3.2, the error occurs. 4、In the sandbox environment, although SKStorefront.countryCode returns the wrong value, the currency type for Apple's in-app purchase is correct when initiating the payment. 5、The issue only exists in the sandbox environment and does not occur in the App Store-downloaded package. Demo Code: - (IBAction)clickButton:(id)sender { NSString *appStoreCountryCode3 = SKPaymentQueue.defaultQueue.storefront.countryCode; NSLog(@"%@",appStoreCountryCode3); } Demo Testing Steps and Results: 1、Sandbox Account A (China) will print "CHN". 2、Go to Settings - Developer - (at the bottom) SANDBOX APPLE ACCOUNT, and switch to another sandbox account B (USA). 3、Restart the Demo App. 4、Print results: iOS 17.5.1: "USA" ✅ → Upgrade the system of the same device to iOS 18.3.2 → "CHN" ❌ iOS 18.2.1: "CHN" ❌ iOS 18.3.1: "CHN" ❌ iOS 18.3.2: "CHN" ❌ Possible Clues: Starting with iOS 18.2, Apple changed the entry point for setting up sandbox accounts, which introduced this bug. It seems that when users switch sandbox accounts on iOS 18.2, Apple engineers forgot to notify the SKStorefront class to update the countryCode value. Before iOS 18.2: Settings - App Store - Sandbox Account iOS 18.2 and later: Settings - Developer - (at the bottom) Sandbox Account Although it doesn't affect the App Store package, it does impact our development and testing process. We hope this issue can be fixed in future versions. Thank you!
5
2
985
Oct ’25
HELP WITH SUBSCRIPTIONS
Hey everyone, I really need help. My app versions keep getting approved for distribution and my subscriptions and business agreements are all approved. Yet, when the paywall in my app appears, and someone clicks the subscribe button to pay, the IAP isn't appearing. It just loads forever. When I tested in Xcode it just kept saying products not found. Id's are the same, bundle id is the same, ive done everything. Can someone help pls.
3
0
218
Jan ’26
App Store StoreKit web hooks doesn't work o=in the Sandbox env.
Hey! We're implementing In-App Purchase Subscriptions and we were able to receive "App Store Server Notifications" on our "Sandbox Server URL". But the last event we received 22 hours ago. We are able to verify transactions and finish them, but receive no webhooks. We changed nothing on our server or its configurations but the notifications stoped to come. We consulted the API (https://api.storekit-sandbox.itunes.apple.com/inApps/v1/notifications/history) and it says the same as we see - the last event was 22hrs ago. I checked all the advices from here as well (https://developer.apple.com/forums/thread/805806?answerId=864483022#864483022). Is there any Status page for the Store Kit Sandbox services? Was there any outage? Sincerely, Konstantin
Replies
2
Boosts
2
Views
196
Activity
Nov ’25
In iOS 26 beta3 version, the finishTransaction method is unable to remove transactions from the SKPaymentQueue, causing transactions to remain in the queue even after being processed.
We have some users who have upgraded to iOS 26 beta3. Currently, we observe that when these users make in-app purchases, our code calls [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; method, and we clearly receive the successful removal callback in the delegate method - (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray<SKPaymentTransaction *> *)transactions. However, when users click on products with the same productId again, the method - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions still returns information about previously removed transactions, preventing users from making further in-app purchases.
Replies
2
Boosts
3
Views
493
Activity
Jul ’25
StoreKit appAccountToken Not Preserved During Apple ID Email Migration
I'm encountering an issue with the App Store Server API where the appAccountToken is not preserved when users migrate their Apple ID email addresses. I've submitted Feedback Assistant ticket FB18709241 but wanted to check if anyone else has experienced this and get community input on best practices. The Issue When a user migrates their Apple ID from one email to another (e.g., from olduser@example.com to newuser@icloud.com), the App Store creates a new subscription transaction with a different originalTransactionId, but the appAccountToken is not carried forward from the original transaction. What I'm Seeing note: these values are fake When querying /inApps/v1/subscriptions/{originalTransactionId} with the either post-migration transaction ID or the pre-migration transaction ID, the API returns both transactions: Pre-migration transaction (status: 2 - inactive): originalTransactionId: "12345678910111" Contains: "appAccountToken": "abc123-def456-ghi789" Post-migration transaction (status: 1 - active): originalTransactionId: "67891011121314" Missing: appAccountToken entirely The Problem The appAccountToken is our only way to link App Store subscriptions to user accounts. Without it on the new transaction: Users lose access to premium features despite having valid subscriptions Server-side renewal notifications can't be matched to user accounts Manual support intervention is required for each affected user Questions for the Community Has anyone else encountered this issue with Apple ID migrations? What's the recommended approach for handling this scenario? Is there an alternative mechanism to maintain the subscription-to-user linkage across migrations? Questions for Apple Engineers Is this the expected behavior, or should the appAccountToken be preserved? Are there any planned improvements to handle this migration scenario? What's the best practice for developers to handle this case? Interestingly, both the old and new transaction IDs return the same JSON response from the App Store Server API, suggesting Apple maintains internal linkage between these transactions, but the appAccountToken isn't carried forward to the active transaction. Any insights or similar experiences would be greatly appreciated! Thank you!! Feedback Assistant: FB18709241
Replies
0
Boosts
3
Views
188
Activity
Jul ’25
85% of Subscriptions are in Billing Retry State
One of our apps has 85% stuck in Billing Retry -- We are so confused. All the users are from the US, and have a one-week free trial. We had 1,000 subscriptions expire from this issue. So any help would be so appreciated.
Replies
2
Boosts
2
Views
220
Activity
Jan ’26
Unknown Error Occurring During Sandbox Purchase Testing
We are experiencing an Unknown Error (error code 0) when testing purchases in the Apple Sandbox environment. The error does not occur every time, but it fails with an Unknown Error in approximately 8 out of 20 attempts. Due to this issue, our app is failing to pass Apple’s review. Issue Details This issue only occurs in the Apple Sandbox environment. After attempting a purchase, the Apple payment API returns SKPaymentTransaction Unknown Error. Returned error code: SKErrorUnknown (error.code 0). This problem is preventing us from conducting proper payment tests and getting approval from Apple. Would it be possible to receive support or any solutions for this issue?
Replies
0
Boosts
2
Views
254
Activity
Mar ’25
Not receiving Sandbox Server-to-Server Notifications for In-App Purchases (App Store Server Notifications v2)
I’m testing auto-renewable subscription purchases in the sandbox environment. When I buy a subscription package using a sandbox test user, I don’t receive any App Store Server Notifications from the sandbox. However, when I use the “Request Test Notification” option in App Store Connect, the notification is received successfully. My sandbox server notification URL is configured correctly and publicly accessible. I also call finishTransaction() after purchase, and the receipt is verified successfully with the sandbox verification endpoint. To further debug, I used the getNotificationHistory API to fetch notifications for yesterday and today (Nov 3–4, 2025). Apple’s API response does not include any notifications or transaction IDs for my today’s purchases (Nov 4, 2025) — even though I can confirm from logs that those transactions were completed and verified successfully. It looks like sandbox purchase notifications are not being sent or logged, even though test notifications work fine. Could someone from Apple please confirm if there’s currently an issue with sandbox server notifications for auto-renewable subscriptions?
Replies
8
Boosts
2
Views
410
Activity
Dec ’25
Appium can't see any locators of purchase 'Sandbox' view
Appium can't see any locators of 'Sandbox' view in case of purchase page automation try. iOS 18.x. On version 17.x the elements could be found
Replies
4
Boosts
2
Views
220
Activity
Apr ’25
App Store Server Notifications and API Client - Toggling Sandbox vs Production Environment
The documentation mentions the following: Verify your receipt first with the production URL; then verify with the sandbox URL if you receive a 21007 status code. This approach ensures you don’t have to switch between URLs while your app is in testing, in review by App Review, or live in the App Store. This way, you can use one server environment to handle both Sandbox and Production environments. It is necessary to pass App Review. However, I'm not manually hitting these URLs - I'm using Apple's libraries. Specifically, the environment is used in SignedDataVerifier and AppStoreServerAPIClient. (I can't link to these because, for some reason, the domain apple.github.io is not allowed. The documentation for these is only found there. You can find it quickly by searching these terms and the domain.) Here is how SignedDataVerifier is being used: const verifier = new SignedDataVerifier( appleRootCertificates, APPLE_ENABLE_ONLINE_CHECKS, APPLE_ENVIRONMENT, APPLE_BUNDLE_ID, APPLE_APP_ID ) const verifiedNotification: ResponseBodyV2DecodedPayload = await verifier.verifyAndDecodeNotification(signedPayload) if (!verifiedNotification) { // Failure return } Here is how AppStoreServerAPIClient is being used: const appStoreServerAPIClient = new AppStoreServerAPIClient( SIGNING_KEY, APPLE_IAP_KEY_ID, APPLE_IAP_ISSUER_ID, APPLE_BUNDLE_ID, APPLE_ENVIRONMENT ) const statusResponse: StatusResponse = await appStoreServerAPIClient.getAllSubscriptionStatuses(originalTransactionId, [Status.ACTIVE]) In the source code for SignedDataVerifier.verifyAndDecodeNotification, I can see that it throws a VerificationException(VerificationStatus.INVALID_ENVIRONMENT) error . So for SignedDataVerifier is it as simple as wrapping my code in a try/catch and checking that the error's status code is 21007? I'm unsure about this because if you scroll to the bottom of the linked source code file, you can see the enumeration VerificationStatus, but it's unclear if this member has a value of 21007. The source code for AppStoreServerAPIClient only says that it throws an APIException if a response could not be processed, so I'm not too sure about how to handle this one.
Replies
2
Boosts
2
Views
961
Activity
Sep ’25
Unexpected 401 Unauthorized response from production endpoint when using sandbox transactionId with Get Transaction Info API
We have encountered an issue when verifying transactions using the Get Transaction Info API. We tested the behavior in both the sandbox and production environments and observed the following results. When calling the production endpoint: https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId} with a transactionId generated in the sandbox environment, the API returns HTTP 401 Unauthorized. However, based on the documentation and common understanding, we expected HTTP 404 Not Found in this case. Using the same JWT token, if we call the sandbox endpoint: https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/{transactionId}, we receive HTTP 200 OK with the expected response body. We have also confirmed that the same behavior occurs when using the Get Transaction History API — it works correctly in the sandbox environment but returns 401 in production. Could you please confirm whether this behavior (receiving 401 instead of 404) is expected by design, or if it indicates a potential issue? If this is not the intended behavior, we would appreciate any guidance or instructions to resolve it. Thank you very much for your technical support. 「Get Transaction Info」APIを用いてトランザクションの検証を行ったところ、以下の問題が発生しました。 サンドボックス環境および本番環境の両方で検証を行い、次の結果を確認しています。 本番環境エンドポイント https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId} に対して サンドボックス環境で生成された transactionId を使用すると、HTTP 401 Unauthorized が返却されます。 (一般的には、この場合 404 Not Found が返る想定であると理解しています。) 同一のJWTトークン を用いて サンドボックス環境のエンドポイント https://api.storekit-sandbox.itunes.apple.com/inApps/v1/transactions/{transactionId} を呼び出した場合は、HTTP 200 OK が返り、期待通りのレスポンスボディを受け取ることができています。 また、同様の挙動が Get Transaction History を使用した場合にも発生することを確認しています。 サンドボックス環境では正常に動作しますが、本番環境では401が返却されます。 この挙動(401が返却されること)は仕様上想定されたものか、または何らかの問題によるものかご確認をお願いいたします。 もし想定外の挙動である場合は、解決に向けたご案内をいただけますと幸いです。 本件について、技術的なサポートをお願いいたします。 よろしくお願いいたします。
Replies
2
Boosts
0
Views
285
Activity
Nov ’25
Don't receive ONE_TIME_CHARGE Notification
the email say this notification type will be available to you in production beginning May 27, 2025, and you can test it in sandbox now. but i didn't receice this notification yet
Replies
1
Boosts
2
Views
167
Activity
May ’25
StoreKit 2 Fails to Load Subscription Products
We are experiencing a critical issue where StoreKit 2 is returning empty products when using Product.products(for:), specifically on devices running iOS 18.4.

 This issue does not occur on iOS 18.3 or earlier.

 Steps:

 Created a subscription product (e.g. "upm1") in App Store Connect
 Confirmed the product is active, localised, and part of a valid subscription group
 Call the following Swift code using StoreKit 2:
 Task { do { let products = try await Product.products(for: ["upm1"]) print(products) } catch { print("Error: (error)") } } 4. Result: products is an empty list.

 This regression is blocking subscription testing on iOS 18.4. 

 Kindly someone please advise on a potential fix or workaround.
Replies
2
Boosts
2
Views
286
Activity
Sep ’25
Auto-renewing Subscription Updates not Arriving
This is a copy of a reply to this post. https://developer.apple.com/forums/thread/722222?page=1 I'm posting as new in the hope someone might have more up-to-date information, as I'm pulling out what little hair I have left. I'm using Storekit 2, testing in Xcode with a local Storekit config file. I have created a very minimal system to investigate this issue. I have a SwiftUI-based window using SubscriptionStoreView, and my app set up with the usual listener. I have four types of auto renewing subscription, configured in the local Storekit config file. With my app running, I subscribe to the lowest-level subscription I offer, via the SubscriptionStoreView. Notification of the inital purchase arrives, but subsequent auto-renewals do not trigger any action in my listener for Transaction.updates. They arrive as expected in the Transaction Manager. Radio silence in my listener. If I upgrade one subscription (via my SubscriptionStoreView) I see this reflected in the UI immediately, and also in the Transaction Manager, but the update that arrives in Transaction.updates refers to the old subscription, and has the isUpgraded flag set to false. Also, can anyone remind me what the grey warning triangle next to entries in the Transaction Manager means. I'm assuming it means unfinished, as that's what the sidebar indicates. Can the testing system really be this broken, or am I wildly off the mark? Unless I'm doing something fundamentally wrong this all seems extremely flakey, but happy to be proved wrong. I find this all rather unsettling if I can't test reliably, and am concerned that I my app may end up in this situation if I use storekit 2: https://stackoverflow.com/questions/73530849/storekit-renewal-transactions-missing-in-transaction-all-or-transaction-updates
Replies
10
Boosts
2
Views
2.2k
Activity
Feb ’26
Cannot Cancel Sandbox Subscription
I did an in app purchase in my development app and now I cannot get rid of it. It is a "monthly" subscription that seems to renew every 1 day. I can see the subscription when I go to settings then tap on Subscriptions. Then I tap the item and choose "Cancel Subscription", revealing a new modal sheet saying "Confirm Cancellation". When I "Confirm", I get the popup: "Your request is temporarily unable to be processed, please try again later". However, this is anything BUT temporary, has gone on for a couple weeks now. As such, I am unable to test subscriptions in my development app. I've tried logging out, restarting, different devices, etc. The phone is logged in under my primary user account, and I may not have been logged into sandbox email when I did the purchase. Can someone forcibly remove it for me?
Replies
2
Boosts
2
Views
700
Activity
Nov ’25
Why does a purchase result in success unverified?
A purchase can result in success with verificationResult .unverified. Is there a list of reasons for which the transaction might be unverified and how should i handle it in my app? From my understanding, a successful unverified transaction means the user has already paid for the purchase. So, do i just ignore the unverified transaction or do i provide content to the user anyways?
Replies
1
Boosts
2
Views
126
Activity
Jul ’25
iTunes v2 notification for freeTrail enabled subscription
"In iTunes IAP space" Give a monthly subscription with 7 days freeTrail, what would be sequence of iTunes V2 notification for the following behaviour? When an end user purchases a subscription that includes a free trial. When the user transitions from the free‑trial period to the paid subscription period.
Replies
2
Boosts
0
Views
154
Activity
Jan ’26
Unable to enable eligibility for External Purchase Link APIs — seeking clarification
Hello, I am currently implementing External Purchase Link and External Purchase Custom Link and am encountering an issue where both ExternalPurchaseLink.canOpen and ExternalPurchaseCustomLink.isEligible always return false under all test conditions. I would like to confirm whether my setup is missing any required steps or whether this behavior is expected. Below are the details of my current environment and configuration: 🔧 1. Development Environment Xcode: 16.3, 16.4, 26.0 beta 4 Devices: iPhone running iOS 26.2 beta iPhone running iOS 16.7.12 macOS 15.5 (real device testing) Simulator iOS 18.0 Build Type: Local development build using a Developer Provisioning Profile Sandbox account signed in during testing 🔑 2. Entitlements (Developer site & Xcode) In Certificates → Identifiers → App ID, both capabilities are enabled: StoreKit External Purchase StoreKit External Purchase Link The .entitlements file in Xcode includes: com.apple.developer.storekit.external-purchase = YES com.apple.developer.storekit.external-purchase-link = YES The Provisioning Profile also contains both entitlements (confirmed via codesign -d --entitlements :-). 📄 3. Info.plist Configuration Both keys are configured with correct region codes according to documentation: SKExternalPurchase SKExternalPurchaseCustomLinkRegions 🌍 4. Test Storefront Device storefront verified as United States (US) or Portugal (PT) (US = target region for External Purchase Link, PT = EU region) But despite all the above configuration, both API calls consistently return false: ExternalPurchaseLink.canOpen // false ExternalPurchaseCustomLink.isEligible // false So I cannot proceed to testing the remaining flow (token retrieval, link opening, etc.) ------ Questions ------ ❓ Q1) Local Development Build Limitation Is it expected behavior that Developer-signed local builds always return canOpen = false / isEligible = false for External Purchase Link & Custom Link? Is there a technical or policy restriction that prevents eligibility in local dev builds? ❓ Q2) App Store Connect Configuration Requirement Are there mandatory App Store Connect settings (such as external purchase URLs, support URL, disclosures, or country configuration) that must be enabled before eligibility becomes true? Currently, no External Purchase Link or Custom Link menu is visible in my App Store Connect app settings. Is this menu only available after certain approvals or under specific conditions? ❓ Q3) TestFlight Requirement Do External Purchase Link and Custom Link only return eligibility = true on: TestFlight builds, or Distribution-signed builds? Or should eligibility also work on developer builds? Formal confirmation would be helpful. ❓ Q4) Developer Account Type Limitation We are using an Individual Developer Account (not Organization). Can Individual accounts fully request, test, and ship apps using: External Purchase Link External Purchase Custom Link Or are there limitations on account type? 🙏 Request We have completed all documented setup steps (Entitlements → Provisioning → Info.plist), but eligibility remains false, blocking feature validation. Please clarify which of the following is the cause: Local development builds do not support eligibility Missing App Store Connect configuration (not visible to us) Account type restriction Region rollout or entitlement approval requirement Any additional setup not documented publicly Thank you for your assistance.
Replies
2
Boosts
1
Views
225
Activity
1w
Unauthorized for Advanced Commerce API Purchase
Hi! My product SKU has been approved for Advanced Commerce API. I successfully receive a purchase pop-up with the correct information. However, I am still having issues with completing the purchase. I always receive Unauthorize error when I confirm the purchase (subscription in my case; see the screenshot). I am using the node.js server library to sign the request. I made sure that the account is a valid account enabled for Sandbox. Logs unfortunately don't indicate any further detail. Thanks for your advice! We've been stuck on this for a while now and would appreciate your help. Marek
Replies
6
Boosts
2
Views
307
Activity
Jul ’25
DID_FAIL_TO_RENEW Notification with a null gracePeriodExpiresDate
We are seeking clarification on the behavior of App Store Server Notifications V2. Summary In our production environment, we received a notification with notificationType: DID_FAIL_TO_RENEW and subtype: GRACE_PERIOD. However, the gracePeriodExpiresDate field in the payload was null. We understand this notification indicates that a user's subscription has entered a grace period. The null value for its expiration date is unexpected, and we are looking for an official explanation of this behavior and the correct way to handle it. The Scenario Here are the details of the notification we received: Notification Type: DID_FAIL_TO_RENEW Notification Subtype: GRACE_PERIOD Environment: Production Upon decoding the signedRenewalInfo JWS from the responseBodyV2, we found that the gracePeriodExpiresDate field inside the JWSRenewalInfoDecodedPayload was null. The notificationUUID for this event was in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Our Implementation and its Impact Our backend is designed to ensure service continuity during a grace period, as recommended in the documentation. Current Logic: Receive the DID_FAIL_TO_RENEW / GRACE_PERIOD notification. Extract the gracePeriodExpiresDate. Extend the user's subscription expiration date in our database to match this date. Because the gracePeriodExpiresDate was null in this case, our logic failed, creating a risk of service interruption for the user. Context and Investigation We have performed the following checks: App Store Connect Settings: We have confirmed that Billing Grace Period is enabled for the relevant subscription group. Sandbox Environment: We have been unable to reproduce this scenario in the Sandbox. User Context: We believe the user in this case was experiencing a failed payment when attempting to renew for the first time after a free trial period. Questions To ensure we handle this scenario correctly, we would appreciate clarification on the following points: Conditions for Null: Under what specific conditions does a DID_FAIL_TO_RENEW notification with a GRACE_PERIOD subtype contain a null gracePeriodExpiresDate? Expected Behavior: Is this null value an expected behavior for certain scenarios, such as the first failed renewal after a free trial? Best Practice: If this is an expected behavior, what is the correct way to handle it? How should our backend interpret a null gracePeriodExpiresDate to ensure service continuity for the user?
Replies
2
Boosts
2
Views
208
Activity
Jul ’25
【iOS18.2~18.3.2 bug】After switching sandbox accounts in Settings, the value of SKStorefront.countryCode is not synchronized
Problem Description: 1、I have two sandbox accounts from different countries. Account A is from Mainland China (CHN), and Account B is from the United States (USA). When I switch the sandbox account from Account A (CHN) to Account B (USA) in the system settings and restart the app, the value of SKPaymentQueue.defaultQueue.storefront.countryCode always returns "CHN" instead of the expected "USA". 2、This issue only occurs on iOS 18.2 and above. 3、On the same device running iOS 17.5.1, the behavior is correct. However, after upgrading the system to iOS 18.3.2, the error occurs. 4、In the sandbox environment, although SKStorefront.countryCode returns the wrong value, the currency type for Apple's in-app purchase is correct when initiating the payment. 5、The issue only exists in the sandbox environment and does not occur in the App Store-downloaded package. Demo Code: - (IBAction)clickButton:(id)sender { NSString *appStoreCountryCode3 = SKPaymentQueue.defaultQueue.storefront.countryCode; NSLog(@"%@",appStoreCountryCode3); } Demo Testing Steps and Results: 1、Sandbox Account A (China) will print "CHN". 2、Go to Settings - Developer - (at the bottom) SANDBOX APPLE ACCOUNT, and switch to another sandbox account B (USA). 3、Restart the Demo App. 4、Print results: iOS 17.5.1: "USA" ✅ → Upgrade the system of the same device to iOS 18.3.2 → "CHN" ❌ iOS 18.2.1: "CHN" ❌ iOS 18.3.1: "CHN" ❌ iOS 18.3.2: "CHN" ❌ Possible Clues: Starting with iOS 18.2, Apple changed the entry point for setting up sandbox accounts, which introduced this bug. It seems that when users switch sandbox accounts on iOS 18.2, Apple engineers forgot to notify the SKStorefront class to update the countryCode value. Before iOS 18.2: Settings - App Store - Sandbox Account iOS 18.2 and later: Settings - Developer - (at the bottom) Sandbox Account Although it doesn't affect the App Store package, it does impact our development and testing process. We hope this issue can be fixed in future versions. Thank you!
Replies
5
Boosts
2
Views
985
Activity
Oct ’25
HELP WITH SUBSCRIPTIONS
Hey everyone, I really need help. My app versions keep getting approved for distribution and my subscriptions and business agreements are all approved. Yet, when the paywall in my app appears, and someone clicks the subscribe button to pay, the IAP isn't appearing. It just loads forever. When I tested in Xcode it just kept saying products not found. Id's are the same, bundle id is the same, ive done everything. Can someone help pls.
Replies
3
Boosts
0
Views
218
Activity
Jan ’26