App Store Connect API

RSS for tag

The 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

148 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Empty "App Store Purchases Detailed" Analytics Report
Hey there, I'm building a service that requires receiving accurate sales/proceeds data along with the campaign name. From reading the documentation it looks to be fairly understandable, but in practice it is not. I have been testing this for almost a week, and I never got "Detailed Report" for "App Store Purchases Detailed" analytics report. The same report for "App Downloads Detailed" is arriving normally, but not to for the purchases. I tested for two different apps where I have around 200 daily installs and 30 purchases on each. I would love to get any thoughts on this from an Apple engineer!
0
0
111
2d
How to build reliable Analytics integration via API?
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.
0
0
175
4d
API calls to get screenshots not working.
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"; } ) ]
1
0
116
1d
How to get base territory for subscriptions with App Store Connect API?
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!!
0
0
127
1w
api.appstoreconnect.apple.com/v1/analyticsReportRequests Endpoint always returns 401 error
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
0
0
138
2w
Base territory for app, in-app purchase
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!
1
0
215
3w
App Store Connect API - Historical pricing for app, IAPs, subscriptions
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!
1
0
176
3w
App Store Connect API: Modify an Auto-Renewable Subscription to change prices for all territories
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
2
0
318
3w
400 : bad gateway error when requesting analytics reports
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.
3
0
270
3w
Sales & finance report API not returning Content-Disposition (File Name) in Response Header
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?
0
2
222
Jan ’25
404 when creating a new Game Center Achievement Localization via API
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.
0
0
222
Jan ’25
cannot read salesReports api response
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?
3
1
392
Jan ’25
Sales of In-App Purchases by Name Data
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!
0
0
230
Jan ’25
Appstore Connect API Territory Availabilities Resource error
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.
2
1
306
Jan ’25
App Store Connect API : Status code 403 on endpoint /v1/salesReports
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
0
0
252
Jan ’25
External Purchase Report 401 error
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); }
1
0
249
Dec ’24
External Purchase Report 401 error
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); }
0
0
279
Dec ’24
Customer Reviews API
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.
0
0
286
Dec ’24