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

165 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

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
41
20h
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
87
1d
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
67
1d
Automatic process in assembling app and send to Apple Store
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!
0
0
48
4d
403 Forbidden Error on responses with "Customer Support" Key Role
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.
2
0
80
1w
Mapping between opaque review IDs and old numeric IDs
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?
0
0
98
3w
UNEXPECTED_ERROR status: 500, when creating profile via app store connect api
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." }
1
0
161
4w
App Store Connect Certificates API
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!
0
0
190
Nov ’24
Guidance needed to pull yesterday's data from perfPowerMetrics endpoint
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!
0
0
180
Nov ’24
How to Dynamically Obtain Device Models for App Store Users?
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!
2
0
223
Nov ’24
Pull data on iOS App Homescreen Widget
Hello fellow developers! I am interested in obtaining the following information regarding one of our Home Screen widgets: Pull the following data about the "my_app_widget" homepage widget in total and by month for the last 12 months (Sep '23 - Sep '24): Widget install events Unique widget installs Device type (iPad, iOS). Thus far, I am using AWS Lambda and have the proper credentials within a Secrets Manager and I keep getting a 409 error from this code: const AWS = require('aws-sdk'); const axios = require('axios'); const jose = require('jose'); const crypto = require('crypto'); const s3 = new AWS.S3(); const secretsManager = new AWS.SecretsManager(); const cloudwatchlogs = new AWS.CloudWatchLogs(); const logGroupName = '/aws/lambda/my_lambda_function'; const logStreamName = '2024/11/05/[$LATEST]XXXXXXXXXXXXXX'; const getSecret = async (secretName) => { const secret = await secretsManager.getSecretValue({ SecretId: secretName }).promise(); return JSON.parse(secret.SecretString); }; const logError = async (message) => { const params = { logGroupName, logStreamName, logEvents: [ { message: JSON.stringify(message), timestamp: Date.now() } ] }; try { await cloudwatchlogs.putLogEvents(params).promise(); } catch (error) { console.error('Failed to log to CloudWatch:', error); } }; const getJwtToken = async (keyId, issuerId, privateKeyPem) => { try { const privateKey = crypto.createPrivateKey({ key: privateKeyPem, format: 'pem', type: 'pkcs8' }); const payload = { iss: issuerId, exp: Math.floor(Date.now() / 1000) + 20 * 60, aud: 'appstoreconnect-v1' }; const token = await new jose.SignJWT(payload) .setProtectedHeader({ alg: 'ES256', kid: keyId }) .sign(privateKey); return token; } catch (error) { await logError({ error: 'Error generating JWT', details: error }); throw new Error('JWT generation failed'); } }; const fetchAndUploadReport = async (url, token, s3Key, isAnalytics = false, body = null) => { try { const headers = { 'Authorization': `Bearer ${token}`, 'Accept': isAnalytics ? 'application/json' : 'application/a-gzip', 'Content-Type': 'application/json' }; const response = await axios({ method: isAnalytics ? 'post' : 'get', url: url, headers: headers, data: body, responseType: isAnalytics ? 'json' : 'stream' }); if (response.status === 200) { let bodyContent = isAnalytics ? JSON.stringify(response.data) : response.data; await s3.upload({ Bucket: 'my_bucket_name', Key: s3Key, Body: bodyContent }).promise(); return { statusCode: 200, body: `${s3Key} fetched and uploaded successfully` }; } else { await logError({ error: 'API response error', status: response.status, statusText: response.statusText, url }); return { statusCode: response.status, body: response.statusText }; } } catch (error) { await logError({ error: 'Error fetching report', url, details: error }); return { statusCode: 500, body: JSON.stringify(`Error fetching ${s3Key}`) }; } }; exports.handler = async (event) => { const secretName = 'AppStoreConnectPrivateKey'; try { const secretData = await getSecret(secretName); const { keyId, issuerId, private_key: privateKeyPem } = secretData; const token = await getJwtToken(keyId, issuerId, privateKeyPem); const startDate = '2023-09-01'; const endDate = '2024-09-30'; const apiEndpoints = [ { url: `https://api.appstoreconnect.apple.com/v1/analyticsReportRequests`, // Changed to request report s3Key: 'my_folder/my_subfolder/unique_widget_installs.json', isAnalytics: true, body: { "data": { "type": "analyticsReportRequests", "attributes": { "accessType": "ONGOING", "name": "Home Screen Widget Installs", "category": "APP_USAGE" }, "relationships": { "app": { "data": { "type": "apps", "id": "YYYYYYYYYYYY" } } } } } } ]; Returns the following error : { "error": "Error fetching report", "url": "https://api.appstoreconnect.apple.com/v1/analyticsReportRequests", "details": { "message": "Request failed with status code 409", "name": "AxiosError", "stack": "AxiosError: Request failed with status code 409\n at settle (/var/task/node_modules/axios/dist/node/axios.cjs:2019:12)\n at IncomingMessage.handleStreamEnd (/var/task/node_modules/axios/dist/node/axios.cjs:3135:11)\n at IncomingMessage.emit (node:events:531:35)\n at IncomingMessage.emit (node:domain:488:12)\n at endReadableNT (node:internal/streams/readable:1696:12)\n at process.processTicksAndRejections (node:internal/process/task_queues:82:21)\n at Axios.request (/var/task/node_modules/axios/dist/node/axios.cjs:4287:41)\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async fetchAndUploadReport (/var/task/index.js:68:26)\n at async Promise.all (index 0)\n at async exports.handler (/var/task/index.js:174:25)", "config": { "transitional": { "silentJSONParsing": true, "forcedJSONParsing": true, "clarifyTimeoutError": false }, "adapter": [ "xhr", "http", "fetch" ], "transformRequest": [ null ], "transformResponse": [ null ], "timeout": 0, "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN", "maxContentLength": -1, "maxBodyLength": -1, "env": {}, So I am not sure if the JSON body I am passing this URL endpoint are correct or if this is the correct API to be using to attempt to obtain this information. Please let me know when you have the chance and I look forward to hearing from you.
0
0
162
Nov ’24
Get Total App Installs
I've been working on retrieving total app installs via the Apple Connect API using Python. However, I've noticed a discrepancy between the data obtained manually and the API results. When I download the Sales & Trends report manually with these settings: Sales & Trends, Monthly, By Territory, Total Installs …the results don't match those from the API when I use the following parameters python report_date = '2024-09' params = { "filter[frequency]": "MONTHLY", "filter[reportDate]": report_date, # Date for the report "filter[reportSubType]": "SUMMARY", "filter[reportType]": "SALES", "filter[vendorNumber]": vendor_number } I’m seeing a clear mismatch in units between the manual download and the API output Note: This report was generated on 2024-11-05
1
0
254
Nov ’24
Accessing Historical Metrics Data with App Store Connect API?
Hi everyone, I’m working with the App Store Connect API to analyze my app's launch time performance, but I’d like to retrieve historical data spanning multiple dates. However, I haven’t found parameters like startDate or endDate in the API documentation. Is there any way to retrieve data for past dates, or is the API limited to recent data only? If anyone has experience with this or any workaround, I’d love to hear about it. Thank you!
0
0
245
Nov ’24
How to Get App Store Connect Metrics by iPhone Model?
Hi Folks, I'm currently using the App Store Connect API's perfPowerMetrics endpoint to pull launch time metrics for my app, but I want to break down the data by specific iPhone models (e.g., iPhone 13 Pro, iPhone 12, etc.). I’ve tried using filter[deviceType] set to all_iphones, which works, but it aggregates data for all iPhone models. Does anyone know the specific identifiers for individual iPhone models, or if there's a way to retrieve metrics by specific iPhone model segments? TIA
2
0
301
Nov ’24