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.
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
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.
i m integrate App Store Server Notifications for External Purchase Server API
The documentation says:
For external purchase tokens that are unreported after 10 days, Apple sends a server notification to your server
https://developer.apple.com/documentation/externalpurchaseserverapi#Receive-notifications-for-unreported-tokens
I have a doubt.
After I'm generating an external purchase token (sandbox), apple notify me 4 times in next 2-3h, even they say, they will notify me after 10 days for unreported tokens.
Mention: Response for notification call was 200
token_create: 13:18
notification_1: 13:58
notification_2: 14:38
notification_3: 15:08
notificaiton_4: 15:38
"notificationType": "EXTERNAL_PURCHASE_TOKEN",
"subtype": "UNREPORTED",
I have no clue what's happening
Hi, I have deployed my app on Test Flight, I have two subscriptions, monthly and yearly. User can have one of them at a time and upgrade, downgrade to the other. Upgrade, downgrade, cancel from the Apple Settings worked fine in the sandbox environment when testing locally. Now when I have deployed the app on TestFlight, I was able to purchase the subscription successfully from my app. Now when I want to cancel my subscription from the Apple Settings it gives me the following error after confirming cancellation, 'Your request is temporarily unable to be processed. Please try again later.' Also the other subscription offer (yearly) is also not shown to which I could upgrade, even though in the sandbox I was able to upgrade downgrade from the settings. Another thing I have noticed is that the app Icon or name is not shown anywhere in settings with the subscription. Instead of app icon only empty square is shown. Even though app icon shows fine everywhere else.
Can someone please help me figure out this issue?
Hi everyone,
I’m currently integrating auto-renewable subscriptions in my React Native app, and I’m encountering an issue with the StoreKit2 API.
What Works
I’ve successfully implemented in-app purchases, and I can purchase auto-renewable subscriptions without any issues. After the purchase, I’m receiving the following transaction details:
``{
"originalTransactionDateIOS": 1732733802000,
"originalTransactionIdentifierIOS": "2000007891139879",
"productId": "product.id",
"transactionDate": 1732748202000,
"transactionId": "2000007935522994",
"transactionReceipt": "xxxxxxxxxxxxCwIBAwIBAQ"
}``
The Problem
When I send the transactionId to my server and call either getTransactionHistory or getTransactionInfo using the App Store Server API, I always receive an empty array as the response.
Additionally, I’ve tried testing with StoreKit Testing in Xcode, but I consistently get 0 as the transactionId, which makes it impossible to verify the transactions.
Here’s what I’ve done so far:
I’m using a sandbox account for testing.
The subscription purchase flow works, and the transactionId is successfully retrieved in the app.
I’ve double-checked that the transactionId sent to the server matches the one from the app.
Thanks in advance!
I need to decode a Base64-encoded receipt from an In-App Purchase and extract the transaction ID from it. However, I want to avoid using the verifyReceipt endpoint since it is deprecated.
Can anyone guide me on how to achieve this manually? Are there any specific libraries, steps, or code samples I should follow to parse the receipt data and retrieve the transaction ID?
Any help or insights would be greatly appreciated!
Hello community,
I recently tested a subscription purchase in my app using a non-sandbox Apple account, and I received the subscription confirmation screen (screenshot attached). However, I’m not sure where I can verify or manage the subscription details for this specific account.
Here are a few points about my situation:
1. The account used for testing is not a sandbox account.
2. The subscription confirmation message displayed correctly in the app.
3. I want to confirm whether the subscription was successfully created or recorded in the App Store.
My questions:
• How can I check the subscription status for this account?
• Is there a specific section in App Store Connect or another platform where I can verify the subscription details for a non-sandbox account used in testing?
• Is it normal to test subscriptions like this, or should I strictly use sandbox accounts for testing?
I appreciate any guidance or resources to help me resolve this. Thank you! 😊
Hi All,
I have setup RevenueCat integration with Apple for in-App purchase, signed all Business Agreements. x-checked all the keys and deleted and created subscription 100 times along with products in RevenueCat but only null is returned to my app by RevenueCat.
I read and discussed with RevenueCat, as per them Apple returns null to them and they revert back null to users.
Can someone please help me, I am struggling and out of wits. Don't know what to do. Any help, will be highly appreciated.
I have some questions regarding the specifications of the receipt information that can be obtained from https://developer.apple.com/documentation/appstoreserverapi/get_transaction_info.
When a subscription is newly purchased, it is expected that the purchaseDate should reflect the time of purchase and should not be later than this time, such as an hour after the purchase. Is this understanding correct?
We observed a phenomenon where, when a user purchased a new subscription between 17:30 and 20:00 JST on November 3, 2024, the purchaseDate in the received receipt was delayed by one hour compared to the actual purchase time. Is this a specification or an issue?
When validating the receipt for a newly purchased subscription, if the purchaseDate reflects a time later than when the purchase was made, should I regard the user as having subscription rights at the time of validation?
How can I check the orders from my app's users? Sometimes users may encounter issues with their payments, so I need to verify the transactions when there are problems reported by my app's users.
Help please. Tell me how to correctly verify a receipt using the apple/app-store-server-library for node.js? After what is the receipt considered verified? Old verifyReceipt is deprecated.
Hello, I am currently encountering an issue while using the server-side API for in-app purchase integration. Suppose a user has already purchased a product, and the App Store returns a transactionId of 1. After some time, the user repeats the purchase for some reason, and the App Store returns a transactionId of 2. However, when I use the Get Transaction History interface to query the transaction information for transactionId 2, I see that the data returned by the App Store does not include the transaction data for transactionId 2; it only contains the transaction data for transactionId 1.
In this situation, my guess is that when the user makes a repeat purchase, the App Store recognizes that the user has already purchased the item and has not executed a refund. Therefore, the App Store generates a new transactionId for this request (the user's purchase) and associates it with the previous purchase's transaction data. This is my inference.
If this user has made 5 repeat purchases, when the user successfully requests a refund, if I query the transaction information through the Get Transaction History interface, will the revocationDate for all 5 transactions in the App Store's official database be modified to the same date? Additionally, after the user successfully refunds and makes another purchase, will the new transactionId still be associated with the previous transaction data?
I'm currently pulling device-specific data for my app, and I'm manually listing 150 models like this:
device_models = [ "iPhone1_1", "iPhone1_2", "iPhone2_1", ... "iPad16_6"]
Is there an API endpoint or an automated method to dynamically retrieve a complete list of device models?
I'm specifically looking to connect this with the performance metrics API to monitor launch times per device type. Any suggestions on how to streamline or automate this list would be greatly appreciated. Thanks!
Hi everyone,
I was just wondering if anyone could point me in the right direction on how to properly handle inquiries about refunding in-app purchases.
I've seen multiple posts saying to direct them to Apple's support, but is there no other direct way of handling this?
Also, does Apple not provide an API to interface with so you can issue refunds on behalf of the customer?
Thanks.
When the verifiyReceipt API is marked as Depreciated, I tried to verify the user's in app purchase order by calling the Get Transaction Info API to query the order information. However, the response did not show a payment success status. How can the APP server confirm whether the user has made the payment? Also, there is an issue of how to perform parameter transparency (that is, when the user makes the payment, the APP calls the Apple server to bring the developer's custom parameters, and then the APP server calls the Apple server API to obtain this parameter), similar to the Payload parameter of the developer in Google's in app purchase
I would like to know if there is a limit to past information in the Look Up Order ID API.
https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id
I understand that you can also get information about users who deleted or reinstalled the app from the content of the document.
On the other hand, are there any temporal limits to the past?
For example, can the above API make requests for purchases made one year ago, five years ago, or ten years ago?
Hello team, why do I occasionally encounter (java. lang. TimeException: com. apple. itunes. storekit. verification. Verification Exception: Verification failed with status INVALID_CHAIN) when calling (BaseAppStoreServerAPIClient. getTransactionInfo) using (app-store-ser-library 3.1.0) in Java
I keep getting 401 Unauthorized error when fetching Apple's public keys.
In [14]: print(f"Error fetching public keys: {response.status_code} {response.text}")
Error fetching public keys: 401 Unauthenticated
I've verified that the Key ID, Issuer ID, and private key file are all correct, with the private key having admin access. The server time is correctly set to UTC. Given this, I can't identify what might be causing the issue. Any insights?
def generate_apple_developer_token():
# Load the private key in PEM format
with open(PRIVATE_KEY_FILE, 'rb') as key_file:
private_key = serialization.load_pem_private_key(
key_file.read(),
password=None,
backend=default_backend()
)
# JWT header
headers = {
"alg": "ES256",
"kid": KEY_ID,
"typ": "JWT"
}
# JWT payload
payload = {
"iss": ISSUER_ID,
"iat": int(datetime.utcnow().timestamp()),
"exp": int((datetime.utcnow() + timedelta(minutes=10)).timestamp()),
"aud": "appstoreconnect-v1",
}
# Encode the header and payload as base64
header_base64 = base64.urlsafe_b64encode(json.dumps(headers).encode()).decode().rstrip("=")
payload_base64 = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
# Concatenate header and payload
message = f"{header_base64}.{payload_base64}".encode()
# Sign the message using ECDSA with SHA256
signature = private_key.sign(
message,
ec.ECDSA(hashes.SHA256())
)
# Convert the DER-encoded signature to raw format (r and s concatenated)
der_to_raw_ecdsa_format = lambda der: der[4:36] + der[-32:]
# Convert the signature to raw format (64 bytes)
signature_64 = der_to_raw_ecdsa_format(signature)
# Base64 URL-encode the signature
signature_base64 = base64.urlsafe_b64encode(signature_64).decode().rstrip("=")
# Concatenate header, payload, and signature to form the JWT
jwt_token = f"{header_base64}.{payload_base64}.{signature_base64}"
return jwt_token
def get_apple_public_keys():
try:
# Generate a fresh JWT
developer_token = generate_apple_developer_token()
# Set up headers with the authorization token
headers = {
"Authorization": f"Bearer {developer_token}"
}
# Fetch the public keys from Apple
response = requests.get('https://api.storekit.itunes.apple.com/in-app-purchase/publicKeys', headers=headers)
# Log the response if it's not successful
if response.status_code != 200:
print(f"Error fetching public keys: {response.status_code} {response.text}")
response.raise_for_status() # Raises an exception for 4xx/5xx errors
# Parse and return the public keys
response_data = response.json()
keys = response_data.get('keys')
if not keys:
print("No 'keys' found in the response from Apple.")
return []
return keys
except requests.exceptions.RequestException as e:
print(f"Error fetching Apple's public keys: {e}")
return []