Signed renewal info from 'Get Subscription Statuses' or in server notifications never has the offerType or offerDiscountType even when the corresponding transaction does have those values set.
Our offer is a free trial.
Do these properties refer to something different in JWSRenewalInfoDecodedPayload than they do in transactions?
I'm trying to determine whether a subscription (identified by originalTransactionId) is currently in a free trial based on server notifications. The status doesn't tell us if the subscription is currently in free trial and the signedTransactionInfo may be for an older transaction.
App Store Server API
RSS for tagCall this REST API from your server to request and provide information about your customers' in-app purchases.
Posts under App Store Server API tag
91 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
We are running auto-renewing subscriptions with StoreKit2 and the “get all subscription statuses” API is behaving unexpectedly.
record the originalTransactionId from the iPhone to the server side when purchasing a subscription with Storekit2.
query the get all subscription statuses API from the server side with the originalTransactionId recorded.
get all subscription statuses returns a response, but there is no data in the response that matches the originalTransactionId.
I have an error on my system because I have built my system on the assumption that all subscriptions including originalTransactionId will be returned.
When using the AppStoreServerAPI to retrieve user purchase information or decode a Payload,
The following responses occur multiple times throughout the day. If there is no error, the process is completed successfully.
HTTP response code: 502 for URL
What is the cause of this error occurring repeatedly? Is there still a problem with Apple's server status?
The following APIs are used to acquire and decode user purchase information.
AppStoreServerAPIClient.getAllSubscriptionStatuses
SignedDataVerifier.verifyAndDecodeTransaction
SignedDataVerifier.verifyAndDecodeRenewalInfo
https://developer.apple.com/documentation/appstoreservernotifications/app-store-server-notifications-changelog#June-10-2024
ONE_TIME_CHARGE notify type running in a sandbox environment for almost a year, the feature is not yet available for production environment.
The notification is already available in Google subscriptions.
Our services often miss orders because of the absence of this notification.
Can you give us an approximate time range?
When the user's purchase information was retrieved from Japan using the AppStoreServerAPI,
I was able to obtain it with the status ‘1: The auto-renewable subscription is active.’,
However, the expiry date in the Payload was the previous day. How can this be the case?
Example: when the purchase information was retrieved on 10/02/2025 at 21:00:00, the expiry date for status ‘1’ was ‘2025/02/09’.
Please let me ask you about the following status code obtained from the AppStoreServerAPI.
3: The auto-renewable subscription is in a Billing retry period.
4: The auto-renewable subscription is in a Billing Grace Period.
5: The auto-renewable subscription is revoked. the App Store refunded the transaction or revoked it from Family Sharing.
For these status codes 3 to 5, would this mean that the service has not been purchased? And will they change to a status of ‘2: The auto-renewable subscription is expired’ after a certain period of time without the payment issue being resolved?
Hi, all!
I have an AppStore Server-side question. User sends up an AppReceipt that I am validating. What's the best way to tell the receipt belongs to said user? I want to make sure that the source of the AppReceipt was actually the original purchaser of the item. Is fetching Transaction + AppAccountToken the only way? AppAccountToken can only be utilized if the original purchase used it, and it is associated with the user's data. Is there another way?
For the subscription API, we’re using the Get All Subscription Statuses API to replace the deprecated verifyReceipt method. To determine if a user has canceled their subscription, we’re using the expirationIntent key from JWSRenewalInfo data. However, we’ve noticed that we sometimes receive this key and other times not.
We’re also facing an issue with the offertype key. We use this key to determine if a user is currently in the introductory offer, the promotion offer, or neither. To obtain this key, we’re using JWSTransaction, but we occasionally receive it and other times not.
Note: These issues are being tested in the sandbox environment.
Thank you.
App Store Server Notifications Not Working in Production Environment
Environment
App Bundle ID: com.fanmuay.app
Environment: Production
Implementation Date: 28/01/2025
Last Successful Sandbox Test: 29/01/2025
Issue Description
I'm experiencing issues with App Store Server Notifications in the production environment. The notifications work perfectly in sandbox, but they stop working completely after moving to production.
What Works
Server notifications are properly received in sandbox environment
All purchase events successfully trigger notifications in sandbox
Notification payload is correctly processed by our server in sandbox
What Doesn't Work
No notifications are being received from production environment
No error messages are being logged
Same implementation that works in sandbox yields no responses in production
Questions
Are there any additional configuration steps needed when moving from sandbox to production for server notifications?
Is there a different certificate or authentication process required for production notifications?
Is there a way to verify if our production endpoint is correctly registered?
Are there any common issues that could cause notifications to work in sandbox but fail silently in production?
Technical Details
Our server is properly configured to receive notifications and can successfully process them in the sandbox environment. The same exact setup is used for production, but we receive no responses. We've verified our server is running and accessible.
Any guidance or suggestions would be greatly appreciated. If you need any additional information, please let me know.
Thank you for your help!
I encountered a scenario involving a subscription and need to determine if it's a problem or an expected outcome. Here are the details:
My service received a notification from Apple of type DID_CHANGE_RENEWAL_STATUS with subtype AUTO_RENEW_DISABLED. The status field received on the payload was equal to 1 - Active. (2024-12-19T15:34:53.801)
My service again received a DID_CHANGE_RENEWAL_STATUS with subtype AUTO_RENEW_DISABLED. But the status field received was 2 - Expired. (2024-12-19T23:34:57.527)
My service received an EXPIRED with subtype VOLUNTARY notification. (2024-12-19T23:35:01.669)
Is the event 2 an inconsistent event? Since we are receiving a notification that means the auto renew was disabled when the subscription was already expired.
I get this error:
Verification failed with status INVALID_APP_IDENTIFIER
we use this method:
payload = signed_data_verifier.verify_and_decode_notification(notification_data)
I use Production environment (this is automatically set in our server) and use my device (connected to Mac) to test the purchase. When trying to purchase I get the Sandbox environment in the Widget.
This works when manually setting the environment to Sandbox before calling the function. The time it works because it does not check the apple app id (because of the environment).
Now my question is: Which is the apple app id? Is it the App Id "Apple-ID" in the app store connect? Or is it the TeamId+BundleId?
Could it be that my function doesnt work because the Payment was done in Sandbox and the environment is Production?
https://developer.apple.com/documentation/appstoreserverapi/get-v2-history-_transactionid
I would like to inquire about the detailed triggers for updating receipts in this API specification.
Recently, I was using this API with sort=DESCENDING&revoked=false to retrieve the expiration date of the most recent receipt and determine the subscription status. However, for some reason, an old receipt with an earlier expiration date appeared as the first receipt, and I would like to know the reason for this.
Can you provide information on what specific events or actions trigger the updating of receipts in this API?
Also, regarding https://developer.apple.com/documentation/appstoreserverapi/status, will statuses 3 and 4 not be returned in the response unless the billing grace period is enabled in the App Store?
https://developer.apple.com/documentation/appstoreserverapi/get-v2-history-_transactionid
I would like to inquire about the detailed triggers for updating receipts in this API specification.
Recently, I was using this API with sort=DESCENDING&revoked=false to retrieve the expiration date of the most recent receipt and determine the subscription status. However, for some reason, an old receipt with an earlier expiration date appeared as the first receipt, and I would like to know the reason for this.
Can you provide information on what specific events or actions trigger the updating of receipts in this API?
Also, regarding https://developer.apple.com/documentation/appstoreserverapi/status, will statuses 3 and 4 not be returned in the response unless the billing grace period is enabled in the App Store?
-- Japanese
こちらのAPI仕様ですが、どのようなトリガーでレシートが更新されるのか詳細に伺いたいです。
先日このAPIを使用してsort=DESCENDING&revoked=falseで一番最初のレシートの有効期限を取得して課金状態か判断していたのですが、どういったわけか一番最初のレシートに古い有効期限のレシートが入ってきたので理由を知りたいです。
また、https://developer.apple.com/documentation/appstoreserverapi/status
のステータスはAppleStoreで請求猶予期間を有効化しないと3,4はレスポンスされませんか?
Hello everyone,
I have some questions regarding the behavior of the offerIdentifier property in the TransactionPayload from App Store Server Notifications.
When a user redeems an Offer Code, the offerIdentifier field is populated with the respective identifier. However, I am unsure how this field behaves in different scenarios, and I would appreciate any insights or clarification:
Does the offerIdentifier persist throughout the subscription lifecycle (from the initial purchase to expiration)?
Does it become null once the Offer Code benefits expire?
Is it only present at the time of purchase and omitted in subsequent notifications?
Additionally, I would like to understand the behavior of the offerIdentifier in the following scenario:
A user purchases a lower-tier subscription using an Offer Code. Later, they upgrade to a higher-tier plan, causing the Offer Code benefits to effectively expire.
What happens to the offerIdentifier in the transaction for the upgrade?
Will it still appear in transactions after the upgrade, or will it be null?
I couldn't find explicit details about these situations in the official documentation, so I hope someone here might have experience or knowledge to share.
Thank you in advance for your help!
We integrated App Store Server notification, to get notified about CONSUMPTION_REQUESTS and REFUND notifications.
In the data, we noticed same transactionId have multiple REFUND decisions, usually REFUND_DECLINED and then REFUND. Why is that? Did user contact customer support ?
For the second (or later) REFUND decision, CONSUMPTION_REQUEST notifications are usually not sent, but thats not always the case. Sometimes, REFUND decision are the same. Sometimes, we get even 3 or more REFUND related notifications for same transactionId, e.g:
2024-12-02: REFUND_DECLINED
2024-12-05: REFUND_DECLINED
2024-12-12: REFUND
Do user request refund again ? Do they contact customer support ? But I can not explain why sometimes status it REFUND at first, but then later REFUND_DECLINED.
Thank you already in advance:)
I encountered a scenario involving a subscription and need to determine if it's a problem or an expected outcome. Here are the details:
My service received a notification from Apple of type DID_CHANGE_RENEWAL_STATUS with subtype AUTO_RENEW_DISABLED. The status field received on the payload was equal to 1 - Active. (2024-12-19T15:34:53.801)
My service again received a DID_CHANGE_RENEWAL_STATUS with subtype AUTO_RENEW_DISABLED. But the status field received was 2 - Expired. (2024-12-19T23:34:57.527)
My service received an EXPIRED with subtype VOLUNTARY notification. (2024-12-19T23:35:01.669)
Is the event 2 an inconsistent event? Since we are receiving a notification that means the auto renew was disabled when the subscription was already expired.
This documentation describes what kind of data we should be sending to Apple server, once we are receiving CONSUMPTION_REQUEST
https://developer.apple.com/documentation/appstoreserverapi/consumptionrequest
But, it doesn't describe what kind of data we are receiving, when we are receiving CONSUMPTION_REQUEST?
May I know, is such a document available?
Thank you.
Hello, Apple App Store Server API Team!
I have one questions about the identifiers provided by Apple App Store Server API. Could you please answer?
We are running an iOS App. In our app, the transactionId we get from Apple App Store Server API is called T1. (Example)
Q1. Is it correct that other iOS apps cannot get T1 for transactionId from Apple App Store Server API? (I'm wondering if the transactionId is globally unique across apps.)
Thank you!
Hi everyone.
I have account and an access to several accounts. When I use List Apps endpoint I get apps only from one account.
Is it possible to get all applications list from api.
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.