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.
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.
Posts under App Store Connect API tag
158 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
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?
Example in-app purchases for a single app:
$0.99
reference name "100 Coins"
product id "smallcoins"
$0.99
reference name "100 Gems"
product id "smallgems"
I can see the proceeds when I download the sales data but cannot tell which one was purchased. How do I differentiate the sales of each in-app purchase on App Store Connect?
Is this something I would need to track in my own database as purchases are made or can I pull this from one of Apple's APIs?
Thanks!
Hi everyone. I active use api and before 8 Jan 2025 receive in headers of response the "x-reports-filename" header as filename of sales and finance reports. I use it for my own goals, but for now this header is not presented.
Does anyone experience the same issue? Is it a bug or "feature"?
I have been trying to do a post request on this appstore api endpoint to be able to set availability on USA territory. However even after following the payload body I still get the error of no matching resource was included.
Here is my payload:
payload = {
data: {
attributes: {
availableInNewTerritories: true
},
relationships:{
app:{
data: { type: "apps", id: app_id }
},
territoryAvailabilities: {
data: [{
id: "#{territory_id}",
type: "territoryAvailabilities"
}]
}
},
type: "appAvailabilities"
},
included: [{
id: "#{territory_id}",
type: "territoryAvailabilities"
}]
}
and this is the api error response I get:
{
"errors" : [ {
"id" : "2c42b5cc-4.....",
"status" : "409",
"code" : "ENTITY_ERROR.RELATIONSHIP.INVALID",
"title" : "The provided entity includes a relationship with an invalid value",
"detail" : "The relationship 'territoryAvailabilities' expects an included resource with type 'territoryAvailabilities' and id 'USA' but no matching resource was included.",
"source" : {
"pointer" : "/included"
}
} ]
}
I am confused as to what the error was referring to as I added the included payload as array and the ids and type match with the territoryAvailabilities relationships as well.
I have certificates that were created using an API key. Is there a way to filter/find them in the App Store Connect API based on created by specific API key?
I’ve been using this code to get automate download units every day for couple months but it’s not working since 22 Dec 2024 until now.
It turns out Failed to retrieve sales report - status code 403
with open(private_key_path, 'r') as key_file:
private_key = key_file.read()
current_time = int(time.time())
payload = {
'iss': issuer_id,
'exp': current_time + 60 * 10, # Token valid for 10 minutes
'aud': 'appstoreconnect-v1'
}
headers = {
'alg': 'ES256',
'kid': key_id,
'typ': 'JWT'
}
token = jwt.encode(payload, private_key, algorithm='ES256', headers=headers)
print(f"Generated JWT Token: {token}")
return token
# API Request setup
url = "https://api.appstoreconnect.apple.com/v1/salesReports"
headers = {"Authorization": f"Bearer {token}"}
params = {
"filter[reportType]": "SALES",
"filter[reportSubType]": "SUMMARY",
"filter[vendorNumber]": VENDOR_NUMBER,
"filter[frequency]": "DAILY",
"filter[reportDate]": report_date
}
try:
response = requests.get(url, headers=headers, params=params, timeout=120)
print(f"Response Status Code: {response.status_code}")
if response.status_code == 200:
# Parse and collect rows
try:
with gzip.open(BytesIO(response.content), 'rt') as gz:
reader = csv.DictReader(gz, delimiter='\t')
rows = list(reader)
print(f"Parsed {len(rows)} rows for {report_date}.")
except Exception as parse_error:
print(f"Error parsing data for {report_date}: {str(parse_error)}")
else:
print(f"Failed to retrieve sales report for {report_date} - Status code: {response.status_code}")
except requests.exceptions.RequestException as request_error:
print(f"Request failed for {report_date}: {str(request_error)}")
Hope there's any advices to help me get through this,
Thank you in advance
Features being implemented
store External Payment Report
Implementation Language and Framework
JAVA springboot
a problem
https://developer.apple.com/documentation/externalpurchaseserverapi/send-external-purchase-report?changes=latest_major
I send jwt tokens in the header to the apple endpoint
If a 401 authentication error occurs all of a sudden while being sent successfully in the beginning, a 401 error has occurred since then
What I checked
Tokens are being re-created and sent every time a report is sent
I'm currently using aws ec2 load balancer and I get 401 error and when I shut down Tomcat and restart it, it works normally and then the above problem occurs again
Even if I send the token that I used to send since 401 happened using postman, 401 error
If my local server issues tokens again with the same content and sends the report to postman, it works fine
Considering the above problems and the confirmed contents, why 401 problems suddenly occur
I'd like to know how to solve that part.
private String keyId="******";
private String issuerId="******";
private String bundleId = "ai.******";
Instant now = Instant.now();
Date issuedAt = Date.from(now);
Date expiresAt = Date.from(now.plusSeconds(20 * 60));
public String createToken(){
try {
PrivateKey key = getPrivateKey();
return Jwts.builder()
.setHeaderParam("alg", "ES256")
.setHeaderParam("kid", keyId)
.setHeaderParam("typ", "JWT")
.setIssuer(issuerId)
.setIssuedAt(issuedAt)
.setExpiration(expiresAt)
.setAudience("appstoreconnect-v1")
.signWith(key, SignatureAlgorithm.ES256)
.claim("bid",bundleId)
.compact();
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("JWT error", e);
}
}
private static PrivateKey getPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
InputStream privateKey = new ClassPathResource("certs/SubscriptionKey_***********.p8").getInputStream();
String result = new BufferedReader(new InputStreamReader(privateKey)) .lines().collect(Collectors.joining("\n"));
String key = result.replace("-----BEGIN PRIVATE KEY-----\n", "")
.replace("-----END PRIVATE KEY-----", "")
.replace("\n", "");
byte[] decoded = Base64.getDecoder().decode(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
return keyFactory.generatePrivate(keySpec);
}
We are producing a function to submit an Apple external purchase report.
When I sent the report, I created a jwt token and put it in the header
There are times when you operate normally and suddenly get a 401 error.
When I checked the entity to log before sending the report, I found that the header was well contained and the token changed every time I called.
Once you get 401 error, you have to shut down your server(tomcat) once and run it again
May I know what kind of problem is causing this phenomenon?
Or can I find a way to fix the problem? The server is using aws ec2 load balancer
The back language is java spring boot
jwt token create code
private String keyId="******";
private String issuerId="******";
private String bundleId = "ai.******";
Instant now = Instant.now();
Date issuedAt = Date.from(now);
Date expiresAt = Date.from(now.plusSeconds(20 * 60));
public String createToken(){
try {
PrivateKey key = getPrivateKey();
return Jwts.builder()
.setHeaderParam("alg", "ES256")
.setHeaderParam("kid", keyId)
.setHeaderParam("typ", "JWT")
.setIssuer(issuerId)
.setIssuedAt(issuedAt)
.setExpiration(expiresAt)
.setAudience("appstoreconnect-v1")
.signWith(key, SignatureAlgorithm.ES256)
.claim("bid",bundleId)
.compact();
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("JWT error", e);
}
}
private static PrivateKey getPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
InputStream privateKey = new ClassPathResource("certs/SubscriptionKey_***********.p8").getInputStream();
String result = new BufferedReader(new InputStreamReader(privateKey)) .lines().collect(Collectors.joining("\n"));
String key = result.replace("-----BEGIN PRIVATE KEY-----\n", "")
.replace("-----END PRIVATE KEY-----", "")
.replace("\n", "");
byte[] decoded = Base64.getDecoder().decode(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
return keyFactory.generatePrivate(keySpec);
}
Hi,
I am trying to connect and use the App Store Connect API so that I can download app reviews remotely. I have read the documentation and have used the API address as stated in the documentation:
GET https://api.appstoreconnect.apple.com/v1/apps/{id}/customerReviews.
I keep on receiving a 403 error:
"errors" : [ {
"id" : "fbe7b837-2023-4f60-8fa0-88b50368f4cc",
"status" : "403",
"code" : "FORBIDDEN_ERROR",
"title" : "This request is forbidden for security reasons",
"detail" : "The API key in use does not allow this request"
}
I am using the same keys and headers that I use to connect to obtain sales reports info, which works absolutely fine, using the below link:
https://api.appstoreconnect.apple.com/v1/salesReports
Is there anything extra that I need to set up before I can access the reviews or am I missing something.
Thanks.
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.
Hello!
We would like to know the steps required to build an application and submit it to the Apple Store using an automated process on a server.
Here are our conditions:
We have a server running macOS Sonoma 14.6.1 on Amazon EC2.
Xcode 16.1 (Build version 16B40) is installed.
We use only console commands, as the GUI is not available.
We use Cordova to add the iOS platform to the application.
A private key, certificate, and provisioning profile have already been created and are located on the server.
Could you please clarify:
What commands are needed to configure the Keychain to use the certificate and provisioning profile?
How can we build the application using xcodebuild?
What are the steps to sign and submit the application to the App Store with minimal human interaction?
Thank you in advance for your assistance!
Is there a way to view the opt-in rate via the API? I have been unsuccessful in finding one.
My company provides an app that allows businesses to connect their Apple Apps to Salesforce so they can manage and respond to their Customer Reviews.
One of our customers has created an API Key for that purpose with a "Customer Support" Role. According to the documentation, that Role should have access to both read and respond to customer reviews:
https://developer.apple.com/help/account/manage-your-team/roles/
We can retrieve Reviews successfully with this API Key. However, whenever they attempt to respond to a Review, they get an error:
[Status=Forbidden, StatusCode=403]
We've confirmed this seems to be related to the Key Role, as they created a new key with an "Admin" role and the response works fine with that key. We don't understand why "Customer Support" doesn't work, though, since the docs seem to indicate that they should support responding to Reviews.
Is there some way to make a "Customer Support" API Key work for responses? If not, are there other roles that would enable them to both read and respond to Customer Reviews? Or is an "Admin" key truly the only Role that would enable responses to Customer Reviews via the API? The customer is understandably hesitant to use an "Admin" key since that opens up a lot of other access.
Error and bak to homepage.
I have an existing system that fetches reviews for an app from the following URL:
https://itunes.apple.com/en/rss/customerreviews/?id=[numeric app ID]
The response from this URL gives review IDs in numeric format, for example 11990822406.
I'd like to use the new API described here to fetch any review response, but the new API only accepts an opaque review ID, for example 00000037-1653-fg99-8224-821b00000000.
Is there any way to map from the numeric review ID to the opaque ID?
Creating profile via a post request keeps getting a server error 500.
It just worked yestday.
POST https://api.appstoreconnect.apple.com/v1/profiles
{
"code": "UNEXPECTED_ERROR",
"detail": "An unexpected error occurred on the server side. If this issue continues, contact us at https://developer.apple.com/contact/.",
"status": "500",
"title": "An unexpected error occurred."
}
I am using an ASO tool.
After linking my Search Ads account campaign with my App Store Connect account, it gets my email and app specific password then makes API call to search ads.
I couldn't find any documentation regarding this flow. Can someone lead me to the correct path where I can implement a similar flow?
Thank you all
Hi all,
I‘m using the certificates API in order to create a development certificate. I want to create a Jenkins job that will give employees an option to create a certificate without giving them admin rights.
I’m creating a new certificate without any issues.
When I try to create another certificate with a different CSR (for a diff user) I get an error that a certificate already exists.
Is it limited to create only one certificate per API key??
Thanks!
Hi Folks, I’m looking to pull performance metrics using https://developer.apple.com/documentation/appstoreconnectapi/get-v1-apps-_id_-perfpowermetrics from Lookback for yesterday's data. Could you guide me on the best way to filter or query this specific timeframe? I dont actually see a way pull data from history. Any advice or steps would be greatly appreciated. TIA!