Hello,
I’m trying to understand which Apple subscription offer best fits a coupon-like flow in our app.
Our ideal case is a 1-month Pro benefit that users can trigger inside the app:
without entering a code manually
possibly more than once over time
then continue into a normal paid auto-renewable subscription
Ideally, this would work for new, existing, and lapsed users, and if possible, even for users who are already actively subscribed (though that part is not required).
From the docs, I understand that:
Offer Codes require redemption
Promotional Offers are for existing or previously subscribed users
Introductory Offers are for new eligible users
Win-Back Offers are for lapsed subscribers
So my questions are:
Is there any Apple-supported way to do this without manual code entry?
Can the same user receive this kind of 1-month benefit multiple times over time?
Which offer type is the closest fit?
Is this use case partly incompatible with Apple’s subscription system?
Thanks.
StoreKit
RSS for tagSupport in-app purchases and interactions with the App Store using StoreKit.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Created
Hey
We have noticed a change in the retry behavior of Apple Server Notifications webhooks V2 starting around March 12–13, 2026.
Previously, when our webhook endpoint returned an HTTP 400 response, Apple would retry the notification delivery multiple times according to the documented retry policy.
However, beginning around March 12–13, it appears that Apple no longer retries the webhook when a 400 response is returned. The notification is sent only once and no further retry attempts are made.
From our understanding of the documentation, retries should occur when delivery fails, and historically we observed retries even for some 4xx responses.
We would like to confirm:
Has Apple recently changed the retry behavior for Server Notifications?
Are HTTP 4xx responses (specifically 400) now considered terminal failures that will not trigger retries?
Is this change intentional or related to a rollout in the webhook delivery system?
We have called the "Notification History" endpoint for some users who purchased a sub and we are only getting one attempt with the following data in it:
{
attemptDate: 1773469202552, (2026-03-14T06:20:02.552Z)
sendAttemptResult: 'UNSUCCESSFUL_HTTP_RESPONSE_CODE',
}
This was 2 days ago, based on the docs, the user should have a few attempts at least.
This behavior change affects systems that rely on retries to handle temporary validation issues or transient failures.
Thanks!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
App Store Server Notifications
App Store Server API
Hi,
my app was rejected because IAP were not present in the app.
I followed guidelines more carefully and filled all buisness detail since then.
And now I have:
StoreKit Configuration in XCode is set to None,
Products (subscription + consumable product) are already approved (from the previous review)
Paid Apps Agreement - active
Bank account - active
Tax forms - active
Compliance - active
Problems:
When trying to test it with TestFlight + sandbox account, StoreKit is returning zero products.
When trying to check my products by "initiate transaction" from Sandbox App Store manage dashboard I am getting an error "This item is not available"
I am totally stuck and don't know what to process next. Unfortunately API.
Hello,
I am investigating a case where two different transaction IDs appear to refer to the same purchase, and I would like clarification on whether this behavior is expected.
Additional context
StoreKit version: StoreKit 1 (SKPaymentTransaction)
Environment: Production
Product type: Auto-renewable subscription
Transaction sources
The values are obtained from the following APIs:
transaction_id from SKPaymentTransaction
https://developer.apple.com/documentation/storekit/skpaymentqueue
receipt_data from the App Store receipt
https://developer.apple.com/documentation/foundation/bundle/appstorereceipturl
Observed behavior
After an In-App Purchase completes, the app receives:
a transaction_id from SKPaymentTransaction
the corresponding receipt_data for the purchase
When inspecting the receipt, the transaction_id inside latest_receipt_info differs from the transaction_id received directly from the purchase transaction.
For clarity:
A = transaction_id received from the purchase flow (SKPaymentTransaction)
A' = transaction_id found in receipt_data.latest_receipt_info
The two values are different, but they differ only by 1.
Additional observation
The original_transaction_id for A and A' is identical, which suggests that both transaction IDs belong to the same subscription purchase chain.
Pattern observation on the ID difference
We have observed that the difference between A and A' is consistently exactly 1 (i.e., A' = A + 1) across multiple transactions, not just a single case.
This appears to be a reproducible pattern rather than a coincidence.
This observation raises an additional question (Question 6 below).
API verification
When calling:
GET /inApps/v1/transactions/{transactionId}
Both A and A' return what appears to be the same purchase record.
The response data is effectively identical except for the transactionId field.
However, when calling:
GET /inApps/v2/history/{transactionId}
A does not appear in the transaction history
only A' appears in the history response
Questions
If A does not appear in transaction history, where does this transaction ID originate from?
Why does Get Transaction Info (/inApps/v1/transactions/{transactionId}) return a valid response for A even though it is not present in the transaction history?
Why do A and A' both resolve to what appears to be the same purchase?
In this situation, which transaction ID should be treated as the canonical transaction ID for server-side validation?
Is this difference related to how StoreKit 1 (SKPaymentTransaction) and the App Store Server API represent transactions?
Is the consistent off-by-one difference between the transaction_id from SKPaymentTransaction and the one recorded in latest_receipt_info an intentional behavior of StoreKit 1's internal transaction ID assignment?
Specifically, we are wondering whether StoreKit 1 applies some form of internal offset when delivering the transaction ID to the client, while the App Store server records a different (adjacent) ID in the receipt. If so, is this documented anywhere?
Note
We are currently in the process of migrating to StoreKit 2, but this behavior was observed while investigating our existing StoreKit 1 implementation.
Any clarification would help us better understand the correct transaction model during the migration.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
Hi everyone,
We are currently working on improving our subscription backend integration with Apple’s App Store Server API and StoreKit, and had a few questions around StoreKit 1 vs StoreKit 2 behavior and server-to-server notifications.
Looking for clarification on the following points:
/inApps/v1/subscriptions/{originalTransactionId} response compatibility
Does the App Store Server API endpoint /inApps/v1/subscriptions/{originalTransactionId} return consistent response structures for subscriptions created via StoreKit 1 and StoreKit 2, or are there any differences we should account for when parsing the response?
Transaction format in S2S notifications for StoreKit 1 purchases
If a user initially purchases a subscription using StoreKit 1, and the subscription renews later, what transaction format is sent in server-to-server notifications?
Does Apple still maintain StoreKit 1 style transaction payloads, or
Are they converted into StoreKit 2–style signed transactions?
Validation of signedTransactionInfo and signedRenewalInfo
In App Store Server Notifications V2, the payload includes signedTransactionInfo and signedRenewalInfo.
Is there an official Apple API endpoint that can be used to validate these tokens?
Offer / coupon identification from S2S notifications
Can server-to-server notifications reliably indicate which offer was applied (intro offer, promotional offer, or offer code)?
If yes, which fields in the transaction payload should be used to identify this?
Trial period identification in StoreKit 2
In StoreKit 1, the field is_trial_period was commonly used to detect free trials.
Since this is deprecated in StoreKit 2, which field or transaction property should be used to identify whether a purchase corresponds to a trial period?
Topic:
App & System Services
SubTopic:
StoreKit
Hello,
Can someone please tell me why the unlock button was unresponsive when tapped? The restore button worked.
if let price = store.product?.displayPrice {
Text(price)
.font(.title2.bold())
.padding(.top, 4)
}
Button {
Task {
await store.purchase()
}
} label: {
ZStack {
if store.isLoading {
ProgressView()
.tint(.white)
} else {
Text("paywall.buy")
.font(.headline)
}
}
.frame(maxWidth: .infinity)
.padding()
}
.background(.blue)
.foregroundStyle(.white)
.clipShape(RoundedRectangle(cornerRadius: 14))
.disabled(store.product == nil || store.isLoading)
Button {
Task {
await store.restorePurchases()
}
} label: {
Text("paywall.restore")
}
Topic:
App & System Services
SubTopic:
StoreKit
Hello,
We are facing an issue with In-App Purchases (subscriptions) in two iOS apps built with React Native + react-native-iap.
Issue
Some users receive the error:
E_CONNECTION_CLOSED
during the purchase flow.
However:
The payment is successfully deducted via the App Store.
The subscription appears in the user's Apple ID subscription list.
But on our side:
The app does not receive the StoreKit transaction callback
No receipt or transaction ID is delivered
Our backend cannot validate the purchase.
Restore Purchases
When affected users try Restore Purchases, StoreKit returns:
No purchases found
even though the subscription is visible in their Apple ID.
Most affected users are from India, and many payments are made via UPI through App Store billing.
Has anyone experienced a case where:
the user is charged
the subscription exists in Apple ID
but StoreKit never returns the transaction or receipt?
Any suggestions on how to recover these transactions would be greatly appreciated.
Thanks!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
In iOS 26.4 beta 4, the receipt returned by StoreKit payments via [[NSBundle mainBundle] appStoreReceiptURL] corresponds to the previous transaction; the content only becomes correct after restarting the app.
Hello,
We are facing an issue with In-App Purchases (subscriptions) in two iOS apps built with React Native + react-native-iap.
Issue
Some users receive the error:
E_CONNECTION_CLOSED
during the purchase flow.
However:
The payment is successfully deducted via the App Store.
The subscription appears in the user's Apple ID subscription list.
But on our side:
The app does not receive the StoreKit transaction callback
No receipt or transaction ID is delivered
Our backend cannot validate the purchase.
Restore Purchases
When affected users try Restore Purchases, StoreKit returns:
No purchases found
even though the subscription is visible in their Apple ID.
Most affected users are from India, and many payments are made via UPI through App Store billing.
Has anyone experienced a case where:
*the user is charged *the subscription exists in Apple ID *but StoreKit never returns the transaction or receipt?
Any suggestions on how to recover these transactions would be greatly appreciated.
Thanks!
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
Hi everyone,
I’ve been encountering a recurring issue with the App Store Server API over the past 48 hours, specifically regarding the Get Transaction Info endpoint.
Endpoint: GET /inApps/v1/transactions/{transactionId}
Environment: Production
Error Code: 4040010 (TransactionIdNotFound)
The Issue
When a user completes a purchase in our app, the client-side sends the transactionId to our backend for validation. However, when our server immediately calls the Get Transaction Info API using that ID, it frequently returns a 4040010 error, stating that the transaction ID cannot be found.
Key Observations
Eventual Consistency Delay: If we implement a retry logic and wait for 2 to 5 minutes, the exact same transactionId eventually becomes queryable and returns a valid signedTransactionInfo.
Notifications vs. API: Interestingly, our server receives the App Store Server Notifications V2 (webhook) for these transactions almost instantly. The notifications contain the correct data, but the "Pull" API seems to lag behind the "Push" notification system.
Recent Spikes: This behavior started occurring frequently within the last 2 days. Prior to this, the API was almost always near-instant.
Questions
Has anyone else noticed a spike in 4040010 errors or increased indexing latency in the Production environment recently?
Is there a recommended "grace period" or backoff strategy when querying for a new transactionId? Apple's documentation doesn't explicitly mention an expected delay between a successful purchase and its availability via the Server API.
Any insights or confirmation of similar issues would be greatly appreciated!
Hi everyone,
I’ve been encountering a recurring issue with the App Store Server API over the past 48 hours, specifically regarding the Get Transaction Info endpoint.
Endpoint: GET /inApps/v1/transactions/{transactionId}
Environment: Production
Error Code: 4040010 (TransactionIdNotFound)
The Issue
When a user completes a purchase in our app, the client-side sends the transactionId to our backend for validation. However, when our server immediately calls the Get Transaction Info API using that ID, it frequently returns a 4040010 error, stating that the transaction ID cannot be found.
Key Observations
Eventual Consistency Delay: If we implement a retry logic and wait for 2 to 5 minutes, the exact same transactionId eventually becomes queryable and returns a valid signedTransactionInfo.
Notifications vs. API: Interestingly, our server receives the App Store Server Notifications V2 (webhook) for these transactions almost instantly. The notifications contain the correct data, but the "Pull" API seems to lag behind the "Push" notification system.
Recent Spikes: This behavior started occurring frequently within the last 2 days. Prior to this, the API was almost always near-instant.
Questions
Has anyone else noticed a spike in 4040010 errors or increased indexing latency in the Production environment recently?
Is there a recommended "grace period" or backoff strategy when querying for a new transactionId? Apple's documentation doesn't explicitly mention an expected delay between a successful purchase and its availability via the Server API.
Any insights or confirmation of similar issues would be greatly appreciated!
在iOS26.4中,新的交易完成后[NSBundle mainBundle] appStoreReceiptURL 获取的是历史票据,未给出新的票据
Topic:
App & System Services
SubTopic:
StoreKit
Hello,
We are currently testing subscription purchases in the Sandbox environment, and we are seeing an issue that we do not fully understand.
When we attempt a single subscription purchase, multiple purchase signals or transaction events are sometimes delivered from Sandbox for what appears to be just one payment attempt. In some cases this happens twice, and in other cases we have seen it occur as many as five to seven times. The number is inconsistent each time, and we have not been able to identify any clear pattern.
At this point, we are not sure whether this is a known instability or limitation of the Sandbox testing environment, or whether there may be something incorrect in our own implementation or configuration.
Has anyone experienced similar behavior when testing auto-renewable subscriptions in Sandbox? If so, we would really appreciate any guidance on what to check.
Thank you.
Topic:
App & System Services
SubTopic:
StoreKit
We are implementing promo/offer codes for our iOS app’s subscription in-app purchases and have several technical questions regarding validation, receipt data, and integration. Could you please provide guidance on the following points?
Testing/Validating Custom Codes Without Production Release: How can we validate custom promo/offer codes in a non-production environment? Current documentation indicates promo codes only work in production, requiring app submission and future release date setup for testing.
Receipt Data for Redeemed Codes: The receipt currently includes only offer_code_ref_name, not the exact redeemed code (e.g., “ABC123”) entered by the user. Is there a way to retrieve the specific offer code used via receipts, App Store Server API, or other endpoints?
Server-Side Validation Best Practices: What are the recommended best practices for server-side validation of offer codes, including using App Store Server API for transaction verification?
Passing appAccountToken for Coupons: How can we pass an appAccountToken when users redeem coupon/offer codes (e.g., via presentOfferCodeRedeemSheet or redemption flows)? StoreKit purchase options support it for regular purchases but not redemption sheets.
Callbacks on Coupon Redemption: Is there a client-side callback or notification (e.g., via updatedTransactions or StoreKit observers) when a user successfully redeems a coupon code in the app? Server notifications are received, but app-side feedback appears unreliable.
Topic:
App & System Services
SubTopic:
StoreKit
Tags:
Subscriptions
StoreKit
In-App Purchase
App Store Receipts
Hello,
I have a question regarding how prorated refunds are reflected when a user upgrades a subscription.
From my understanding, when a user upgrades to a higher-tier subscription, the remaining value of the current subscription is refunded as a prorated amount, typically represented as REFUND_PRORATED or PRORATED_CREDIT.
However, when reviewing the available transaction history and refund-related data (including the App Store Server API and transaction history endpoints), I cannot find any field or record that clearly indicates:
the actual prorated refund amount, or
the credit applied when upgrading to another subscription
In other words, while the concept of REFUND_PRORATED seems to exist conceptually, I cannot identify where the actual prorated value or credit applied to the upgrade is exposed in the transaction or refund history.
My questions are:
Is there any way to retrieve the actual prorated refund or credit amount when a user upgrades a subscription?
Is this information available through the App Store Server API (e.g., Get Transaction History) or any other API endpoint?
If not, is there any recommended method to determine how much of the previous subscription was credited toward the upgraded subscription?
Any clarification would be greatly appreciated.
Thank you for your help.
Topic:
App & System Services
SubTopic:
StoreKit
I am testing a consumable in-app purchase in the StoreKit sandbox and I am seeing behavior that does not seem correct on repeat purchase attempts.
Product details
Product ID: album.credit.v2
Type: Consumable
Test environment: iOS device + StoreKit sandbox
Purchase flow triggered from my Flutter app using Apple IAP
What happens
First purchase attempt works
My backend receives the confirmation
The album is granted correctly
On the second purchase attempt of the same consumable, I do not get a normal new purchase flow
Instead, StoreKit returns the product as restored
My app then cancels the attempt because a restored transaction arrived during checkout
Expected behavior
Because this product is a consumable, each purchase attempt should behave like a new purchase and allow the user to buy it again.
Actual behavior
On the second attempt, the transaction update comes back as restored instead of a new successful consumable purchase.
Relevant logs
First successful purchase:
[ProPurchasePage] ✅ Pay tapped. starting=false iap=true albumProd=album.credit.v2 proProd=pro.monthly
[IAP] update: id=album.credit.v2 status=PurchaseStatus.restored pendingComplete=false err=null
[IAP] expected=album.credit.v2 starting=true appleFlow=true
[ProPurchasePage] album credit success status=PurchaseStatus.restored receiptLen=5334
[AppleIapService] Sending Apple IAP confirmation for albumId=ariie_west_pretty_girl_summer, buyerUid=PYjgu9TMCieCVDLIdTuawY5k4Ay2
[AppleIapService] appleIapConfirm response status: 200
[AppleIapService] appleIapConfirm applied for albumId=ariie_west_pretty_girl_summer buyerUid=PYjgu9TMCieCVDLIdTuawY5k4Ay2
After that, the purchase is written correctly on my side:
"libraryAlbums": [
{
"AlbumId": "ariie_west_pretty_girl_summer",
"paid": true,
"Quantity": 1
}
]
Second and later attempts:
[ProPurchasePage] ✅ Pay tapped. starting=false iap=true albumProd=album.credit.v2 proProd=pro.monthly
[ProPurchasePage] buyConsumable (album.credit.v2) returned: true
[IAP] update: id=album.credit.v2 status=PurchaseStatus.restored pendingComplete=false err=null
[IAP] expected=album.credit.v2 starting=true appleFlow=true
[IAP] restored arrived during album checkout — cancelling attempt
Question
Is this expected StoreKit sandbox behavior for a consumable, or does this suggest:
a StoreKit sandbox issue,
a problem with how the product is configured in App Store Connect,
or a transaction-handling issue in the app/plugin layer?
Also, is there any Apple-recommended handling for repeated consumable purchases when sandbox keeps surfacing a restored status?
Topic:
App & System Services
SubTopic:
StoreKit
Hello DTS team, the request review from StoreKit is not working in iOS 26.4 beta 3. I have filed a feedback (FB22157147).
Sample code:
import SwiftUI
import StoreKit
struct ContentView: View {
@Environment(\.requestReview) private var requestReview
@State private var count = 0
var body: some View {
VStack {
Button("Increase Count") {
count += 1
}
Text(count, format: .number)
.font(.largeTitle)
}
.onChange(of: count) {
if count == 3 {
Task {
try await Task.sleep(for: .seconds(2))
requestReview()
print("Request Review triggered!")
// On iPadOS 26.4 beta 2 & 3, requestReview() does not trigger any review system sheet when testing in Xcode 26.3
// Works on iOS 26.3.1
}
}
}
}
}
Hello,
I am currently testing In-App Purchases for my app in the Sandbox environment.
Our app has two types of products:
Auto-renewable subscriptions
Non-renewing subscriptions
When testing auto-renewable subscriptions, I can see the subscription in the Sandbox account management screen, and I can perform actions such as:
Viewing the active subscription
Cancelling the subscription
Upgrading or downgrading the subscription
However, when testing non-renewing subscriptions, I cannot find the purchase history anywhere in the Sandbox account management screen.
Because of this, I cannot verify whether the non-renewing subscription purchase was recorded correctly.
My question is:
Where can I check the purchase history for Non-Renewing Subscriptions in the Sandbox environment?
Is there a specific place in:
App Store Connect
Sandbox account settings
Or somewhere else
where these purchases can be reviewed?
Thank you in advance for your help.
Topic:
App & System Services
SubTopic:
StoreKit
The developer payment page is returning a 503 error, preventing me from making the payment. Why is this happening? I need to complete this payment urgently.