Hey there,
I'm building a service that requires receiving accurate app downloads and sales/proceeds data along with the campaign name. From reading the documentation it looks to be fairly understandable, but in practice it is not that straightforward.
For example, I received the first one-time-snapshot detailed report for the App Store Purchases, and it contains partial data for several days. Shouldn't that be a full report of everything in analytics for like last year or so? Should I expect it to be updated and extended in the coming days?
For the ongoing detailed report, I have not received anything yet, but I'm afraid it might have partial data as well. I will report here as well.
App Store Connect API
RSS for tagThe App Store Connect API helps you automate tasks usually done on the Apple Developer website and App Store Connect.
Post
Replies
Boosts
Views
Activity
I am attempting to upload an application to the app store. The selected method was using Transporter through terminal commands. In this sense, I keep receiving a metadata error which is as follows :
Command (Assume values are filled in)
/usr/local/itms/bin/iTMSTransporter -m upload \
-u "MY_EMAIL" \
-p "YOUR_APP_SPECIFIC_PASSWORD" \
-f "/Users/isseyyohannes/Desktop/ALGORA_Performance.itmsp" \
--asc-provider "GL5BCCW69X" -v detailed
I receive the following error
Package Summary:
1 package(s) were not uploaded because they had problems:
/Users/isseyyohannes/Desktop/ALGORA_Performance.itmsp - Error Messages:
ERROR ITMS-3000: "Line 9 column 25: element "data_file" incomplete; missing required elements "checksum" and "size" at XPath /package/software_assets/asset/data_file"
ERROR ITMS-3000: "Line 12 column 24: element "software_metadata" not allowed here; expected the element end-tag or element "metadata_token" at XPath /package/software_metadata"
ERROR ITMS-3000: "Line 13 column 19: element "software" not allowed here; expected the element end-tag or element "game_center", "in_app_purchases", "products", "read_only_info" or "versions" at XPath /package/software_metadata/software"
ERROR ITMS-3000: "Line 16 column 28: element "bundle_id" not allowed anywhere; expected element "read_only_value" at XPath /package/software_metadata/software/read_only_info/bundle_id"
ERROR ITMS-3000: "Line 17 column 30: element "app_version" not allowed anywhere; expected element "read_only_value" at XPath /package/software_metadata/software/read_only_info/app_version"
ERROR ITMS-3000: "Line 18 column 33: element "product_family" not allowed anywhere; expected element "read_only_value" at XPath /package/software_metadata/software/read_only_info/product_family"
ERROR ITMS-3000: "Line 19 column 30: element "read_only_info" incomplete; missing required element "read_only_value""
ERROR ITMS-3000: "Line 20 column 20: element "software" incomplete; expected element "software_assets" or "software_metadata""
ERROR ITMS-3000: "Package "null" failed schema validation."
[2025-02-19 15:45:07 EST] <main> DBG-X: Returning 1
Essentially just a bunch of warnings about my metadata file which I edited manually to read the following
<?xml version="1.0" encoding="UTF-8"?>
<package version="software5.10" xmlns="http://apple.com/itunes/importer">
<provider>GL5BCCW69X</provider>
<team_id>GL5BCCW69X</team_id>
<software_assets>
<asset type="bundle">
<data_file>
<file_name>ALGORA_Performance.pkg</file_name>
<checksum type="sha1">7acb9fcb19eb203bdc6038f88d06a67386900b28</checksum>
<size>75619323</size>
</data_file>
</asset>
<software_metadata>
<software>
<vendor_id>93274081</vendor_id>
<read_only_info>
<read_only_value key="bundle_id">com.algora.ALGORA-Performance</read_only_value>
<read_only_value key="app_version">0.0.0</read_only_value>
<read_only_value key="product_family">macOS</read_only_value>
</read_only_info>
</software>
</software_metadata>
</software_assets>
</package>
Last note is that I manually created the metadata.xml file and moved it via local terminal for fear of having to use XCode which I am not familiar with.
ANY HELP IS APPRECIATED
Hi am new to App Store Connect api calls.
First tried all apps url and it works(let url = URL(string: "https://api.appstoreconnect.apple.com/v1/apps")! )
But I want to get screenshots for an app. and it gives an error.
JWT Payload: {
aud = "appstoreconnect-v1";
exp = "761634503.157082";
iat = "761633363.157082";
iss = "69a6de6e-6715-47e3-e053-5b8c7c11a4d1";
scope = (
"GET /v1/apps/{appId}/appScreenshotSets",
"GET /v1/apps"
);
}
let url = URL(string: "https://api.appstoreconnect.apple.com/v1/apps/\(appId)/appScreenshotSets")!
HTTP Status Code: 400
["errors": <__NSSingleObjectArrayI 0x600000010320>(
{
code = "ENTITY_INVALID";
detail = "Invalid scope GET /v1/apps/{appId}/appScreenshotSets";
id = T6VMMMF3V4NGO7Z3AO4AHOU2QI;
links = "";
status = 400;
title = "JSON processing failed";
}
)
]
I am currently testing my in app subscription via sandbox. I am able to make the purchase and verify it, but it will not auto renew. The sandbox account is flagged as being subscribed, so it can't be purchased again, but I don't actually get the auto renewal.
I did notice that randomly on app boot up, I'll get a bunch of the backlogged auto renewals come in, but they are never actually sent to me when the 3 minute expiration is finished.
This is on macOS, so I am not able to actually look at and manage the sandbox subscriptions. It seems like that's only a thing for iOS. Is this just a behavior with the sandbox environment or will this behavior also happen with legitimate App Store?
The code I use is below:
@MainActor
func updateCustomerProductStatus() async {
var purchasedSubscriptions: [Product] = []
for await result in Transaction.currentEntitlements {
do {
let transaction = try checkVerified(result)
switch transaction.productType {
case .autoRenewable:
if let subscription = subscriptions.first(where: { $0.id == transaction.productID}) {
purchasedSubscriptions.append(subscription)
}
default:
break
}
} catch {
print("catching \(error)")
}
}
init() {
subscriptions = []
updateListenerTask = listenForTransactions()
Task {
await requestProducts()
await updateCustomerProductStatus()
}
}
deinit {
updateListenerTask?.cancel()
}
func listenForTransactions() -> Task<Void, Error> {
return Task.detached {
// Iterate through any transactions that don't come from a direct call to `purchase()`.
for await result in Transaction.updates {
do {
let transaction = try self.checkVerified(result)
// Deliver products to the user.
await self.updateCustomerProductStatus()
// Always finish a transaction.
await transaction.finish()
} catch {
// StoreKit has a transaction that fails verification. Don't deliver content to the user.
print("Transaction failed verification.")
}
}
}
}
Hi
I want To Upload My first IPA file on Apple Store
but when I Upload it I get this error
Validation failed (409)
Missing required icon file. The bundle does not contain an app icon for iPhone / iPod Touch of exactly '120x120' pixels, in .png format for iOS versions >= 10.0. To support older versions of iOS, the icon may be required in the bundle outside of an asset catalog. Make sure the Info.plist file includes appropriate entries referencing the file. See https://developer.apple.com/documentation/bundleresources/information_property_list/user_interface (identifiant : 731ce968-747f-4ba6-a2d0-4a6c306c6eb2)
Hello,
I would like to ask about how to handle subscription refund notifications.
Here’s what I’ve done.
Environment: Sandbox
Steps to reproduce
1.Subscribe.
2.Request a refund using beginRefundRequest.
3.Receives App store server notifications.
I expected to receive the EXPIRED notification immediately after receiving the REFUND notification, but I have confirmed that the EXPIRED notification is received on the renewal date.
We plan to restrict access to premium content when receiving the EXPIRED notification.
If a user starts an annual subscription in January and requests a refund after 3 months, will the EXPIRED notification be received in January of the following year?
If so, what is the optimal time to restrict access to premium content?
Additionally, is there a possibility of a partial refund?
Thank you in advance for your support!
Hello all,
In the App Store Connect API:
Apps have /v1/appPriceSchedules/{id}/baseTerritory.
IAPs have /v1/inAppPurchasePriceSchedules/{id}/baseTerritory.
...but:
Auto-renewing subscriptions don't have a corresponding endpoint for getting the base territory
However, the App Store Connect website does indeed require you to set a base territory when creating new auto-renewable subscriptions.
Why's that?
More importantly, what's the best way of determining what to use for a base territory?
Thank you!!
I use PHP language to obtain our App customer reviews and generate token code as follows:
$privateKeyResource = PRIVATE_KEY;
$keyId = KEY_ID;
$alg = 'ES256';
$token = JWT::encode([
'iss' => '29960467-xxxx-xxxx-xxxx-2aa42ec3e66d',
'iat' => time(),
'exp' => time() + 300,
'aud' => 'appstoreconnect-v1',
"scope" => [
"GET /v1/customerReviews",
]
], $privateKeyResource, $alg, $keyId, [
"alg" => "ES256",
"kid" => $keyId,
"typ" => "JWT"
]);
But the api responds with 403, detailed response:
{"errors":[{"id":"26I4HZDVWBVNX5HI33OINP753Q","status":"403","code":"FORBIDDEN.REQUEST_DOES_NOT_MATCH_SCOPE","title":"This request does not match the scope specified in the API token.","detail":"The request RequestData(method=POST, path=/v1/appStoreVersions/1612795156/customerReviews, query=null) does not match any authorized scope: [RequestData(method=GET, path=/v1/customerReviews, query=null)]","links":{"see":"https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests"}}]}
Hi all,
I am facing an issue with the api.appstoreconnect.apple.com/v1/analyticsReportRequests endpoint. I always get a 401 error when making POST requests to it. The JWT is generated with a team key having Admin access and it works when I make GET requests, so calling api.appstoreconnect.apple.com/v1/apps is successful for example. The body of the POST request is
"data": {
"type": "analyticsReportRequests",
"attributes": {
"accessType": "ONGOING"
},
"relationships": {
"app": {
"data": {
"type": "apps",
"id": "my_app_id"
}
}
}
}
}
Anyone else with the same problem or with some idea on what I might be doing wrong.
Many thanks in advance
Symeon
Hello!
I'm using the App Store Connect API to get some pricing information for my apps and in-app purchases. If I'm understand correctly, I first need to get the base territory and then get pricing schedules for that territory, and the process looks to be the same across both App information and In-App Purchase information, even though those each use different API endpoints.
My question is about Base Territory. I thought that was a thing that's the same across an entire App Store Connect team, but I see these two APIs:
(1) Read the base territory for an app's price schedule
and
(2) Read the selected base territory for an in-app purchase price schedule
The fact that both of these exist implies that IAPs can have a different base territory than the app itself, and that different apps can have different base territories, or even that different IAPs in the same app could have different base territories. Is that actually true?
Or, do both APIs exist for convenience - so that if you're dealing with an IAP you can use that API instead of the app API, for example?
The reason I'm asking is that I'd like to be as efficient as possible with API calls.
Right now, in order to get prices for all apps in my account and all IAPs, I believe I need to call:
To fetch all pricing information:
/v1/apps - Get list of all apps
For each app:
/v1/appPriceSchedules/{appId}/baseTerritory - Get base territory
/v1/appPriceSchedules/{appId}/manualPrices?filter[territory]={territoryId} - Get prices for base territory
/v1/apps/{appId}/inAppPurchasesV2?include=iapPriceSchedule - Get IAPs
/v1/apps/{appId}/subscriptionGroups?include=subscriptions - Get auto-renewable subscriptions
For each IAP:
If type is NOT non-renewing subscription:
/v1/inAppPurchasePriceSchedules/{iapId}/baseTerritory - Get base territory
/v1/inAppPurchasePriceSchedules/{iapId}/manualPrices?filter[territory]={territoryId} - Get prices
If type IS non-renewing subscription OR auto-renewable subscription:
/v1/subscriptions/{iapId}/prices?filter[territory]={territoryId} - Get subscription prices
This is getting what we want, but hat's a LOT of API calls. Are there steps here we can shortcut or cut out? I'm looking for the current, manually-set prices for everything.
Thanks very much!
Hello!
I'm using the App Store Connect API and am trying to find out if there is a way to get historical pricing for apps, in-app purchases, and/or subscriptions? I see https://developer.apple.com/documentation/appstoreconnectapi/get-v1-apppriceschedules-_id_, as well as similar APIs for in-app purchases and subscriptions, but those don't appear to return (or give a way to return) anything historical.
Thanks!
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!
Hello,
I want to update the prices in all territories of an auto-renewable subscription at once (in a single request). I know it's possible to do it territory by territory using the Create a Subscription Price Change API endpoint, but this means I need to call this API for every territory. And I have a lot of subscriptions I need to update.
There is an another API endpoint that seems to allow to Modify an Auto-Renewable Subscription.
For the countries where I want to change the price, I fetch the subscription price points using the List All Price Points for a Subscription API endpoint.
When I call this API endpoint with the following body (that is the expected body content for this endpoint):
{
"data": {
"type": "subscriptions",
"relationships": {
"prices": {
"data": [
{
"id": "eyJzIjoiNjc0MDAyMTQ5NiIsInQiOiJDQU4iLCJwIjoiMTAwMDEifQ",
"type": "subscriptionPrices"
},
{
"type": "subscriptionPrices",
"id": "eyJzIjoiNjc0MDAyMTQ5NiIsInQiOiJVU0EiLCJwIjoiMTAwMDEifQ"
}
]
}
},
"id": "6740021496"
},
"included": [
{
"relationships": {
"subscriptionPricePoint": {
"data": {
"id": "eyJzIjoiNjc0MDAyMTQ5NiIsInQiOiJDQU4iLCJwIjoiMTAwMDEifQ",
"type": "subscriptionPricePoints"
}
},
"territory": {
"data": {
"type": "territories",
"id": "CAN"
}
},
"subscription": {
"data": {
"id": "6740021496",
"type": "subscriptions"
}
}
},
"id": "eyJzIjoiNjc0MDAyMTQ5NiIsInQiOiJDQU4iLCJwIjoiMTAwMDEifQ",
"attributes": {
"preserveCurrentPrice": true
},
"type": "subscriptionPrices"
},
{
"attributes": {
"preserveCurrentPrice": true
},
"id": "eyJzIjoiNjc0MDAyMTQ5NiIsInQiOiJVU0EiLCJwIjoiMTAwMDEifQ",
"type": "subscriptionPrices",
"relationships": {
"subscription": {
"data": {
"type": "subscriptions",
"id": "6740021496"
}
},
"subscriptionPricePoint": {
"data": {
"type": "subscriptionPricePoints",
"id": "eyJzIjoiNjc0MDAyMTQ5NiIsInQiOiJVU0EiLCJwIjoiMTAwMDEifQ"
}
},
"territory": {
"data": {
"type": "territories",
"id": "USA"
}
}
}
}
]
}
I receive a 409 error:
{
"errors" : [ {
"id" : "5b6a4b62-686c-4a65-87ba-e16131db517b",
"status" : "409",
"code" : "ENTITY_ERROR",
"title" : "There is a problem with the request entity",
"detail" : "User is not allowed to edit.",
"source" : {
"pointer" : "subscriptionPrices"
}
} ]
}
I made sure
my bearer authorisation token is correct and still valid (not expired).
the p8 key has Admin rights
Can this PATCH endpoint be used for what I want to do? If yes, is there anything special to do to use this PATCH endpoint?
Thanks,
Axel
Hello,
I have tried this method
curl -X POST
-H "Authorization : Bearer [my_Token]"
-H "Content-Type: application/json" --data-binary @"data.json"
https://api.appstoreconnect.apple.com/v1/analyticsReportRequests
with the contents of "data.json" being :
{
"data": {
"type": "analyticsReportRequests",
"attributes": {
"accessType": "ONE_TIME_SNAPSHOT"
},
"relationships": {
"app": {
"data": {
"type": "apps",
"id": "[my_appid]"
}
}
}
}
}
in order to send a POST request reports request to the apple store connect API, as per this https://developer.apple.com/documentation/appstoreconnectapi/post-v1-analyticsreportrequests documentation, but with no success. I have made sure my JWT is correct :
headers = {
"alg": "ES256",
"kid": [my_private_keyid],
"typ": "JWT"
}
payload = {
"iss": [my_issuer_id],
"iat": int(date_emission.timestamp()),
"exp": int(date_expiration.timestamp()),
"aud": "appstoreconnect-v1",
"bid": "[my_bundleid]"
}
as per this https://developer.apple.com/documentation/appstoreserverapi/generating-json-web-tokens-for-api-requests documentation.
I have also made sure my key is an admin key as it is required in order to send such a request, and I have used JSON online verificators to make sure my JSON is correct, as I was expecting it to be a JSON related issue. I really can't seem to understand why I only get 400 : bad gateway responses, any help would be appreciated on the matter.
I'm trying to use the App Store Connect API to get the list of expired certificates. When I make the web service call:
https://api.appstoreconnect.apple.com/v1/certificates
I'm able to get the list of developer certificate. The distribution certificates are not included in the list. According to the docs, I should all of them in the result set.
Is there any thing special that needs to be added the web service call to have the distribution certs included in the result set?
As part of ConsumptionRequest fields there's a bit of unclarity. In my case I am only concerned with subscriptions, as they give some premium features in the app.
The fields and the questions are the following:
playTime: is this the time used in the app in total or just the time the app has been used while using the subscription?
consumptionStatus: does this relate only to the user using the premium features he/she paid for? or the fact that the user had access to those features only?
Thanks!
We have been using apple Sales report API (https://api.appstoreconnect.apple.com/v1/salesReports) to fetch the sales report. It has been running for over a year without any issues.
But recently Starting JAN 15. The API is not returning Content-Disposition header which usually contains Filename additionally, x-report-filename which also contains the filename information is missing. We are not able to save the files without the filename.
We do not see any update to the Sales Reports API in the documentation.
Is there any reason for this sudden change? Is there any alternative to get the name from the API or will this be fixed?
Hello!
I've put together a script that synchronizes my game's Game Center Achievement status with a couple of spreadsheets that define them, including their many translations.
I've got the JWT authentication working, got a list of achievements, and successfully created the ones that didn't exist.
I'm now iterating over the localizations under each achievement, but I'm stuck because an API end point is giving me a 404 and I can't work out why.
The URI I'm posting to is https://api.appstoreconnect.apple.com/v1/gameCenterAchievementLocalizations as per the documentation.
I might expect a 404 if I wasn't authorized, but my key is definitely authorized to create new achievements, because I've done that.
I know that the API will give me back reasonable response codes if my data is bad, as I've seen 409 Conflict, 422 Unprocessable etc. when developing previous parts of the script. Even if it might give a 404 for reasons of bad data, I've eyeballed the data and it looks exactly like the example.
I'm stuck where to go next with diagnosis when the URL matches exactly. Is it possible the documentation is out of date? I did try POSTing to https://api.appstoreconnect.apple.com/v1/gameCenterAchievements/xxxxx/localizations (where *** is the game center id) and it gave me a 405 Not Allowed, which was very clear.
Thanks for any suggestions.
I am receiving a 405 when sending a POST request to this endpoint. The documentation is here: https://developer.apple.com/documentation/appstoreconnectapi/add_a_scheduled_price_change_to_an_app
Can you tell me what method I should be using to add a scheduled price change to an app using this endpoint?
we have a schedule calling https://api.appstoreconnect.apple.com/v1/salesReports
everday, and after 2025/01/15 08:40:03 (GMT+8) the response started to parse fail
1.the api return http status 200, but the respose is not readable (save bytes as .txt and open)
2.there was a response header "x-reports-filename" but not exist now
our program never change for at least 5 years, and I don't find any update of salesReports api
how can we solve it?