Based on my research, I have formed the following understanding; is this correct?
- Regarding Case A (behavior when a purchase is made using a production account connected to Apple's Sandbox environment):
① What kind of account do reviewers use for testing?
Reviewers use Apple's internal review devices and dedicated Apple accounts for review purposes.
Although the build being reviewed is a "production binary," StoreKit communication within the review environment is forcibly routed to the "Sandbox environment" by Apple's systems.
The reviewers' accounts are configured within Apple's internal systems as "special tester accounts" authorized for Sandbox in-app purchase testing.
② Does StoreKit block this on the client side?
It is not blocked.
While regular users attempting to make a purchase using a production account in a development build would be rejected with a "Not a Sandbox account" error, Apple configures the system so that reviewer accounts successfully authenticate within the review sandbox.
When a reviewer taps the purchase button, the purchase confirmation sheet (displaying "[Environment: Sandbox]") appears; authentication succeeds, and a successful purchase completion transaction is issued. Naturally, the reviewer is not actually charged.
③ Backend behavior (Why 4040010 is returned)
Purchase transactions completed by the reviewer are recorded only on Apple's "Sandbox server."
Consequently, when the backend queries the production App Store Server API using the transactionId sent from the app, it returns a 4040010 (TransactionIdNotFoundError) because the transaction does not exist in the production database.
However, if the backend automatically falls back to querying the Sandbox API, it can successfully retrieve a "200 OK" response along with the transaction details (JWS).
- Case B: Behavior after Sandbox environment data is invalidated (clearing purchase history for pending reviews and testing "Restore Purchases")
① Behavior when "Restore Purchase" is executed within the app
If the "Restore Purchase" button (calling AppStore.sync() or SKPaymentQueue.restoreCompletedTransactions()) is pressed immediately after the reviewer has deleted the purchase history from the device:
Since no valid purchase history exists on the Apple server, StoreKit returns "0 transactions to restore" (an empty array).
Points to note (to avoid app rejection):
If the app misinterprets this state—where there are zero items to restore—as a "communication error" or "unknown error" and displays an error alert or enters an infinite loading loop, it becomes a common cause for rejection due to guideline violations (such as Guideline 2.1 or 3.1.1). Instead, the app must display a standard alert indicating that "no restorable purchases were found" and complete the process gracefully.
② Querying the App Store Server API using a previous transactionId
If the backend subsequently queries Apple's Sandbox Server API using a transactionId received prior to the history being cleared:
Because the record has been purged on Apple's end, the Sandbox API will return a 4040010 (TransactionIdNotFoundError) error.
Client-side:
Do not implement custom logic on the app side to restrict purchase processing based on whether the account is a production or sandbox account; instead, rely on the standard StoreKit flow.
If "Restore Purchases" returns zero results, handle the UI flow normally—treating it as "no valid purchases" rather than an error.
Server-side:
Requests from reviewers appear to originate from a production build, but the underlying data consists of sandbox transactions.
Therefore, having a mechanism in place that automatically falls back to the Sandbox API upon receiving a 4040010 error from the Production API is a prerequisite for passing the review smoothly.