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.

App Store Connect API Documentation

Posts under App Store Connect API subtopic

Post

Replies

Boosts

Views

Activity

Data gaps on App Store Analytics API reports
Hey all, It's been now a few weeks since we started to help clients connect to their App Store Analytics API. I'm starting to notice that very often we'll see things like: Small data gaps. Eg. I have data on June 1, no data on June 2-4, and then data from June 5 to now Big data gaps. Eg. I'd have data on Jan 2024, but not on Feb-Mar 2024, then there's data again from April 2024 onwards. The actual files from Apple are like that we're not doing any treatments whatsoever. That's happening on both ONGOING and ONE_TIME_SNAPSHOT I also opened a Customer Support case and sent the files over 10 days ago, but no definitive answer so far. Are you also seeing gaps like this on your data? Any tips/recommendations?
4
0
1.6k
Dec ’25
Promotional Offer ID column is empty in Subscriber report for redeemed offer code
When redeeming a custom offer code, I'm not able to see the actual offer code ID in the Subscriber report - only the subscription offer name is present. I'm going off of the documentation for the Promotional Offer ID column: A code that you create for customers to enter and redeem the subscription offer. https://developer.apple.com/help/app-store-connect/reference/subscriber-report Is the documentation wrong? How are we supposed to measure the performance of our offer codes beyond the initial redemption? For example, with the offer name I can see how my "Holiday Promos" offer is doing but can't see the actual performance of "BLACKFRIDAY30" vs "MOTHERSDAY30".
1
0
636
Aug ’25
JWT Fails with Individual Key on App Store Server API
We want to use the App Store Server API for in-app purchase validation. Due to circumstances, we cannot use the team-based private key (team key) and must use an individual authentication key. However, the JWT authentication keeps failing when using the individual key. Could there be an issue with our code? $jwtHeaderArray = [ 'alg' => 'ES256', 'kid' => $this->KID_ID, 'typ' => 'JWT' ]; $jwtBodyArray = [ 'sub' => 'user', 'aud' => $this->ACCESS_TOKEN_AUD, 'iat' => time(), 'exp' => time() + 3600, "scope" => [ "GET /inApps/v1/transactions" ]
1
0
379
Apr ’25
Get the list of distribution certificates from app connect api
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?
1
0
402
Apr ’25
Create app in Appstore using AppStoreConnect API is giving an error.
Hello Apple Developer Team, I've followed the AppStoreConnect API documentation and created the following: I've created a API Key in App store > Integrations > Teams key, gave the role as admin. Created a valid JWT token When fetching the GET v1/apps, I can see the list of apps. Also I was able to make GET v1/users as well successfully. I've the valid bundle Id and capabilities enabled in the developer portal. Facing an issue while creating an app in App Store using AppStoreConnect API using POST call: This is my ruby script: response = api_request( method: :post, path: "/v1/apps", token: token, body: { data: { type: 'apps', attributes: { name: APP_NAME, primaryLocale: LOCALE, sku: "SKU#{Time.now.to_i}", bundleId: BUNDLE_ID, platform: 'IOS' } } } ) It gives me below error: { "errors": [ { "id": "09b465fc-316f-47b4-9bc3-9c340cb966aa", "status": "403", "code": "FORBIDDEN_ERROR", "title": "The given operation is not allowed", "detail": "The resource 'apps' does not allow 'CREATE'. Allowed operations are: GET_COLLECTION, GET_INSTANCE, UPDATE" } ] } Did anyone was able to successfully create the app in App Store via AppStoreConnect API? Could you please help me identify the root cause for the above issue and provide some inputs so that I could work on resolving them and move forward in the deployment process. Appreciate your help in reviewing this. Thank you, Santosh
0
0
228
Apr ’25
Requesting Code-Level Support: Node.js Script to Fetch US Education Apps with "Exam Prep" by Revenue
Hi Apple Developer Support, I’m working on a Node.js script to fetch all apps listed under the Education category and Reference subcategory from the US App Store, where the app name includes "exam prep". My goal is to list these apps in descending order of their earned revenue (including both paid apps and those with subscriptions). To proceed, I’m looking for guidance or code-level support on: Accessing App Store metadata programmatically via Apple-approved APIs. Filtering apps by category, subcategory, and keywords in the app name. Sorting the result set by revenue (paid and subscription earnings). Is there any recommended API or service (official or via App Store Connect) that I should be using to achieve this? Appreciate any direction, documentation, or sample code that can help. Thanks in advance!
0
0
139
Apr ’25
decode profileContent
Hi, I'm using the https://developer.apple.com/documentation/appstoreconnectapi/get-v1-profiles api to fetch our provisions profiles and decoding them using bash but it looks like the outputs also encoded in a other way, can someone help me fix my code? Many thanks! Example of the beginning of the output profileContent output: 01 *H 101 1 0 + �0"� *H ! !<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>AppIDName</key> .... Code: output=$(curl -X GET \ -H "Authorization: Bearer $jwt" \ -H "Content-Type: application/json" \ --globoff "https://api.appstoreconnect.apple.com/v1/profiles?fields[profiles]=name,profileContent,profileState") while read row; do name=$(echo -n "$row" | jq -r .attributes.name) profileState=$(echo -n "$row" | jq -r .attributes.profileState) profileContent=$(echo -n "$row" | jq -r .attributes.profileContent | base64 -d) done < <(echo "$output" | jq -c '.data[]')
2
0
126
Apr ’25
App Store Connect shows more data than salesreports API
We're using https://api.appstoreconnect.apple.com/v1/salesReports (https://developer.apple.com/documentation/appstoreconnectapi/get-v1-salesreports) to get the First-Time Downloads as can be seen in the App Store Connect per app. But from the API we only get data since March 2025 while in the App Store Connect data can be seen since November 2022. From the API response we read the Units for entries where 'Product Type Identifier' is 1 (https://developer.apple.com/help/app-store-connect/reference/product-type-identifiers/) per Apple Identifier. The results is for all apps as we expect, but for one app we only get data since March 2025. It is indeed the case that the app has been published in March, but the same id was in use since November 2022, under another vendor though (different vendorNumber, which we don't know). Is there any way to get the statistics from before March, like can be seen in the App Store Connect? Perhaps another way of calling salesReports or another API. We tried https://appstoreconnect.apple.com/analytics/api/v1/data/timeseries as that is the call happening in App Store Connect which over there is returning data prior to March 2025, but we couldn't get it to work nor find documentation about it. Or can we feed the old data so we would get it back from salesReports?
0
0
141
Apr ’25
How to Best Practices for Implementing In-App Purchases (IAP) in Mobile Apps and Backend Systems
Hello everyone, I’d like to ask for your input regarding best practices for implementing In-App Purchases (IAP) across both the frontend and backend. Here’s our current flow: -Frontend (Mobile) The user opens a specific page. We initiate a payment request using react-native-iap. After the user completes the payment, we send the purchase data (receipt) to our backend. Backend: Accept the purchase receipt from the app. Validate the receipt with Apple’s server. (GET https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId}) If the receipt is valid and the response indicates success, we mark the payment status as PAID. We store the transaction ID in our payment module. The Issue: We recently encountered a situation where Apple returned a valid receipt, so we marked the transaction as PAID. However, later we realized that the payment status was actually Pending. { transactionId: '70002676245699', originalTransactionId: '70002676245639', bundleId: '', productId: '', purchaseDate: 1745560404000, originalPurchaseDate: 1745560404000, quantity: 1, type: 'Consumable', inAppOwnershipType: 'PURCHASED', signedDate: 1745981078460, environment: 'Production', transactionReason: 'PURCHASE', storefront: 'SGP', storefrontId: '', price: 5000, currency: 'SGD', appTransactionId: '' } This raised a few questions: Does a Pending status always resolve to Paid, or is there a risk that Apple may later mark it as Failed or Unpaid? Is there a specific field in Apple's receipt response that reliably indicates whether the purchase is truly active? Should we hold off on granting access or product delivery until the status transitions from Pending to Paid? We’d really appreciate any insights or recommendations on how to handle this edge case to avoid granting access prematurely. Thanks in advance!
0
0
213
Apr ’25
App Store Connect Metrics via REST API
I hope this message finds you well. I’m reaching out to ask whether specific App Store Connect metrics available in the App Analytics dashboard can also be accessed via the App Store Connect REST API. I have reviewed the official API documentation, but I couldn’t find confirmation regarding the metrics listed below. Could you kindly clarify if the following metrics are available through the REST API? And if so, could you point me to the relevant endpoints or documentation? From the "Usage" group: Installations (Opt-in only) Active Devices Deletions (Uninstalls) From the "App Store" group: Impressions (Unique Devices) Product Page Views (Unique Devices) If these metrics are not available via the REST API, is there an alternative method to programmatically access or export them? Thank you very much in advance for your help and guidance.
2
0
229
May ’25
Apple Connect API
Hello, can any help to set a price change to any of our In-Apps programmaticly(C#). I'm have no problem to create the token and i get positive results for GET calls (like In-App purchase data or Apple PriceTemplates). My Get call is a simple HttpClient GetAsync(id) so I supposed I need a HttpClient PostAsync(url, content). The result is a "404 NotFound" which is no error shown for this call. I searched a lot to fix the error but I found nothing that is explaining this error. My content is created like this: var content = new StringContent(jsonmodel, Encoding.UTF8, "application/json"); My URL: https://api.appstoreconnect.apple.com/v1/inAppPriceSchedules My JsonModel: { "data": { "relationships": { "baseTerritory": { "data": { "id": "DEU", "type": "territories" } }, "inAppPurchase": { "data": { "id": "6448129561", "type": "inAppPurchases" } }, "manualPrices": { "data": [ { "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ", "type": "inAppPurchasePrices" } ] } }, "type": "inAppPurchases", "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ" }, "included": [ { "attributes": { "startDate": null, "endDate": null }, "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ", "relationships": { "inAppPurchasePricePoint": { "data": { "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ", "type": "inAppPurchasePricePoints" } }, "inAppPurchaseV2": { "data": { "id": "6448129561", "type": "inAppPurchases" } } }, "type": "inAppPurchasePrices" } ] } regards kas
0
0
104
May ’25
Creating Advanced AppClip Experiences Via API
I'm trying to programmatically create an Advanced AppClip Experience via the API. following the docs https://developer.apple.com/documentation/appstoreconnectapi/app-clips-and-app-clip-experiences I have created the header image. But when I try to create the experience I can not figure out a) how to create a localisationID to be included in the relationships object b) how to get the included object to be recognised Any one have experience or can offer help?
1
0
126
May ’25
I can't verify App Store Notification
I'm setting up App Store Notifications for my app. Having trouble verifying even the TEST notification, through. I'm generating JWT-token and sending it via Postman. I get a successful notification UUID as a response. But my Node.JS endpoint says it can't verify it. Here's the endpoint: const fs = require('fs'); const path = require('path'); const { SignedDataVerifier, Environment } = require('@apple/app-store-server-library'); module.exports = function (sqlexec) { function loadRootCAs() { // const gPath = path.resolve(__dirname, "AppleIncRootCertificate.cer"); const g3Path = path.resolve(__dirname, "AppleRootCA-G3.cer"); // const g2Path = path.resolve(__dirname, "AppleRootCA-G2.cer"); const loadedCerts = []; try { // loadedCerts.push(fs.readFileSync(gPath)); loadedCerts.push(fs.readFileSync(g3Path)); // loadedCerts.push(fs.readFileSync(g2Path)); if (loadedCerts.length === 0) { throw new Error("No Apple Root CA certificates were loaded."); } console.log("[APPLE NOTIFICATIONS2] Apple Root CA certificates loaded successfully."); return loadedCerts; } catch (error) { console.error("❌ CRITICAL: Error loading Apple Root CA certificate(s):", error.message); console.error("Ensure 'AppleRootCA-G3.cer' (and others if specified) are present at the expected path and readable."); throw new Error("Failed to load essential Apple Root CA certificates. Notification processing will fail."); } } const appleRootCAs = loadRootCAs(); const enableOnlineChecks = true; const environment = Environment.SANDBOX; const bundleId = "SomeBundleID"; const appAppleId = undefined; // Set if you're in PRODUCTION const verifier = new SignedDataVerifier( appleRootCAs, enableOnlineChecks, environment, bundleId, appAppleId ); router.post('/notifications_refund', async function (req, res) { const signedPayload = req.body.signedPayload; try { const notificationVerificationResult = await verifier.verifyAndDecodeNotification(signedPayload); if (!notificationVerificationResult.isValid) { console.error(`[APPLE NOTIFICATIONS2] Failed to verify notification. Status: ${notificationVerificationResult.verificationStatus}, Error: ${notificationVerificationResult.errorMessage || 'N/A'}`); return res.status(400).json({ status: "error", message: "Invalid notification signature or payload." }); } const decodedNotification = notificationVerificationResult.payload; const notificationType = decodedNotification.notificationType; const subtype = decodedNotification.subtype; if (notificationType === 'TEST') { console.log(`[APPLE NOTIFICATIONS2] Received TEST notification. Subtype: ${subtype}`); // The TEST notification's data.signedTransactionInfo is a JWS representing a sample transaction. } else if (notificationType === 'REFUND') { console.log(`[APPLE NOTIFICATIONS2] Received REFUND notification. Subtype: ${subtype}`); } else { console.log(`[APPLE NOTIFICATIONS2] Received notificationType: ${notificationType}, Subtype: ${subtype}. Skipping non-refund/test type for this endpoint.`); return res.status(200).json({ status: "success", message: "Notification received, but not a type processed by this refund endpoint." }); } // Ensure data and signedTransactionInfo exist if (!decodedNotification.data || !decodedNotification.data.signedTransactionInfo) { console.error("[APPLE NOTIFICATIONS2] Notification payload is missing data or signedTransactionInfo."); return res.status(400).json({ status: "error", message: "Notification missing transaction info." }); } const transactionInfoJWS = decodedNotification.data.signedTransactionInfo; const transactionVerificationResult = await verifier.verifyAndDecodeTransaction(transactionInfoJWS); if (!transactionVerificationResult.isValid) { console.error(`[APPLE NOTIFICATIONS2] Failed to verify signedTransactionInfo. Status: ${transactionVerificationResult.verificationStatus}, Error: ${transactionVerificationResult.errorMessage || 'N/A'}`); return res.status(400).json({ status: "error", message: "Invalid signedTransactionInfo in notification." }); } const verifiedTransactionPayload = transactionVerificationResult.payload; const transactionId = verifiedTransactionPayload.originalTransactionId || verifiedTransactionPayload.transactionId; console.log(`[APPLE NOTIFICATIONS2] Successfully decoded Transaction ID: ${transactionId} for notification type ${notificationType}`); // This is where my refund logic starts in case the notif is refund, but fow now I'm just trying to verify a TEST notif return res.status(200).json({ status: "success", message: "Refund (or TEST) notification processed successfully and validated." }); } catch (error) { console.error("[APPLE NOTIFICATIONS2] Critical error processing notification:", error); // Check if the error is from the verifier or elsewhere if (error.name === 'SignedDataVerificationError') { // Example, check actual error type from library return res.status(400).json({status: "error", message: `Notification verification failed: ${error.message}`}); } return res.status(500).json({ status: "error", message: "Failed to process notification due to an internal server error." }); } }); return router; }; I tried different root certs, only G3 works, other two give errors. Also tried adding G3 intermediate (WWDRCAG3), but it doesn't seem to help. What am I doing wrong?
0
0
71
May ’25
App Store Analytics API Reports
Hi everyone, I’m new here. I’m working with the App Store Connect (ASC) Analytics API and I have some questions about how to retrieve historical data for downloads and in-app purchases. I’ve created two types of reports: 1. ONGOING: Retrieves current and recent data. 2. ONE_TIME_SNAPSHOT: Supposedly retrieves historical data. I am specifically interested in the Detailed versions: • App Store Downloads Detailed • App Store Purchases Detailed What's my problem? 1. The ONGOING report brings instances with data from the last few days, which seems correct for App Downloads. But not with Purchases, it brings just a few random days and I'm not sure about the granularity. 2. The ONE_TIME_SNAPSHOT report, however, retrieves instances with data from specific days, but the selection of these days appears to be random. I can’t figure out the criteria behind it. Does anyone know what the selection criteria are for the days that appear in the ONE_TIME_SNAPSHOT report? Is it possible to configure the date range for this type of report? Why are some historical dates available while others are not? Is there a way to ensure that the ONE_TIME_SNAPSHOT report brings data from all days within a specified range? Any advice or insights would be greatly appreciated! Thanks in advance!
0
0
243
May ’25
Retrieving each user’s “last login” timestamp via the App Store Connect API – is it possible?
Hello everyone, I’m building a custom tool that uses the App Store Connect API (v1) to manage my team’s users. I can successfully list all users with: GET https://api.appstoreconnect.apple.com/v1/users …but the JSON response only includes fields like firstName, lastName, email, allAppsVisible, provisioningAllowed, and roles. There is no lastLogin or timestamp field anywhere in the User object: { "data": [ { "id": "USER_ID", "type": "users", "attributes": { "firstName": "mohit", "lastName": "tiwari", "email": "", "allAppsVisible": false, "provisioningAllowed": false }, "relationships": { … } }, … ] } My main question is: How can I retrieve each user’s “last login” timestamp via the App Store Connect API? Is this even possible with the current endpoints? If it isn’t exposed, has Apple any plans to add this? Or are there any recommended workarounds—perhaps via audit logs or another API—to track when each user last accessed App Store Connect? Thanks in advance for your guidance and any code/endpoint examples you can share!
0
0
124
May ’25
App Store Connect API: 'UNIVERSAL' is not a valid value for the attribute 'platform'
Hello, We are encountering an issue when using the App Store Connect API to create a bundle ID via the endpoint: POST https://api.appstoreconnect.apple.com/v1/bundleIds In our request, we specify the platform value "UNIVERSAL", which according to the official documentation is a valid value: BundleIdPlatform documentation However, the API now returns the following error response: { "errors": [ { "code": "ENTITY_ERROR.ATTRIBUTE.TYPE", "detail": "'UNIVERSAL' is not a valid value for the attribute 'platform'. Expected one of: 'IOS', 'MAC_OS'", "status": "409", "title": "An attribute in the provided entity has the wrong type" } ] } According to the documentation, the platform attribute accepts the following values: IOS, MAC_OS and UNIVERSAL. It appears that UNIVERSAL is no longer accepted even though it is still listed as a valid option. Has support for UNIVERSAL been deprecated or changed recently? If so, what is the current recommended way to create bundle IDs that are intended for multiple platforms? Any clarification would be greatly appreciated. Thank you!
0
0
162
Jun ’25
DEVELOPER_ID_APPLICATION_G2 is not recognized by ASC API
Hi, ASC API call rejects DEVELOPER_ID_APPLICATION_G2 and does not recognize it, even though it is listed as a valid certificateType in the docs: https://developer.apple.com/documentation/appstoreconnectapi/get-v1-certificates. If it was removed from the certificate list, then why Apple forces to choose the G2 type when creating a DEVELOPER_ID_APPLICATION certificate manually in the Apple Developer account. Can someone from Apple support please check it as it is a contradictory behavior and is a blocker.
2
0
151
Jun ’25
Customer review forbidden error message despite successful auth
Hi, I am seeking assistance and feedback on the below post on feedback assistant. FB18169176 (Customer review API forbidden error) I am calling this endpoint in a python script: https://api.appstoreconnect.apple.com/v1/apps/6450458286/customerReviews?limit=200&sort=-createdDate I can verify that I am getting a valid JWT token. An example is on the feedback link. Yet I am getting this error: { "errors" : [ { "id" : "eda3b456-9aa9-47bd-8736-439db0c73545", "status" : "403", "code" : "FORBIDDEN_ERROR", "title" : "This request is forbidden for security reasons", "detail" : "The API key in use does not allow this request" } ] } Please advise why this is the case, and please assist as this information is needed urgently. Thank you.
0
0
69
Jun ’25
External Purchase: status 401
Good morning, I am configuring in backend the sending of reports regarding purchases made in app with external platform (Stripe) as per documentation. To be clear I am talking about ExternalPurchase. However, when I make the call it returns "Apple responded with status 401". I verified the token on jwt.io as per documentation and it is working. I don't understand where I am going wrong. Below I share the code with you: const express = require("express"); const bodyParser = require("body-parser"); const jwt = require("jsonwebtoken"); const fs = require("fs"); const app = express(); const https = require("https"); const APPLE_KEY_ID = "XXXXX"; const APPLE_ISSUER_ID = "xxx-xxx-xxx-xx-xxxxxx"; const APPLE_PRIVATE_KEY = fs.readFileSync("AuthKey_xxxxx.p8", "utf8"); const APPLE_AUDIENCE = "appstoreconnect-v1"; function generateAppleJwt() { const now = Math.floor(Date.now() / 1000); const payload = { iss: APPLE_ISSUER_ID, iat: now, exp: now + (5 * 60), aud: APPLE_AUDIENCE }; return jwt.sign(payload, APPLE_PRIVATE_KEY, { algorithm: "ES256", header: { alg: "ES256", kid: APPLE_KEY_ID, typ: "JWT" } }); } app.post('/webhook', bodyParser.json({ type: 'application/json' }), async (req, res) => { let eventType = req.body.type; const relevantEvents = [ "invoice.paid" ]; if (relevantEvents.includes(eventType)) { try { const data= req.body.data; const platform = data.object.subscription_details.metadata.platform; if (platform === "IOS") { const token = generateAppleJwt(); const applePayload = { appAppleId: "xxxx", bundleId: 'com.xxx.xxx.test', externalPurchaseId: data.object.id, purchaseTime: new Date(data.object.created * 1000).toISOString(), purchaseAmount: { amount: (data.object.total / 100).toFixed(2), currencyCode: data.object.currency.toUpperCase() }, purchaseLocation: { isoCountryCode: "IT" } }; const jsonString = JSON.stringify(applePayload); const agent = new https.Agent({ keepAlive: false }); const response = await fetch( "https://api.storekit-sandbox.apple.com/externalPurchase/v1/reports", { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", "Accept-Encoding": "identity", }, body: JSON.stringify(applePayload), } ); if (!response.ok) { const errorText = await response.text(); throw new Error( `Apple responded with status ${response.status}: ${errorText}` ); } console.log("✅ Notifica inviata ad Apple con successo"); } else { if(!canSendNotification){ console.log("Non è una Sub. Nessuna notifica inviata."); }else{ console.log("Customer non iOS. Nessuna notifica inviata."); } } } catch (err) { console.error("Errore durante l’invio ad Apple:"); if (err.response) { console.error("Status:", err.response.status); console.error("Headers:", err.response.headers); console.error("Data:", err.response.data); } else { console.error("Message:", err.message); } } } res.status(200).send("OK"); }); exports.checkSubStripe = functions.https.onRequest(app);
0
0
126
Jun ’25
Data gaps on App Store Analytics API reports
Hey all, It's been now a few weeks since we started to help clients connect to their App Store Analytics API. I'm starting to notice that very often we'll see things like: Small data gaps. Eg. I have data on June 1, no data on June 2-4, and then data from June 5 to now Big data gaps. Eg. I'd have data on Jan 2024, but not on Feb-Mar 2024, then there's data again from April 2024 onwards. The actual files from Apple are like that we're not doing any treatments whatsoever. That's happening on both ONGOING and ONE_TIME_SNAPSHOT I also opened a Customer Support case and sent the files over 10 days ago, but no definitive answer so far. Are you also seeing gaps like this on your data? Any tips/recommendations?
Replies
4
Boosts
0
Views
1.6k
Activity
Dec ’25
Promotional Offer ID column is empty in Subscriber report for redeemed offer code
When redeeming a custom offer code, I'm not able to see the actual offer code ID in the Subscriber report - only the subscription offer name is present. I'm going off of the documentation for the Promotional Offer ID column: A code that you create for customers to enter and redeem the subscription offer. https://developer.apple.com/help/app-store-connect/reference/subscriber-report Is the documentation wrong? How are we supposed to measure the performance of our offer codes beyond the initial redemption? For example, with the offer name I can see how my "Holiday Promos" offer is doing but can't see the actual performance of "BLACKFRIDAY30" vs "MOTHERSDAY30".
Replies
1
Boosts
0
Views
636
Activity
Aug ’25
JWT Fails with Individual Key on App Store Server API
We want to use the App Store Server API for in-app purchase validation. Due to circumstances, we cannot use the team-based private key (team key) and must use an individual authentication key. However, the JWT authentication keeps failing when using the individual key. Could there be an issue with our code? $jwtHeaderArray = [ 'alg' => 'ES256', 'kid' => $this->KID_ID, 'typ' => 'JWT' ]; $jwtBodyArray = [ 'sub' => 'user', 'aud' => $this->ACCESS_TOKEN_AUD, 'iat' => time(), 'exp' => time() + 3600, "scope" => [ "GET /inApps/v1/transactions" ]
Replies
1
Boosts
0
Views
379
Activity
Apr ’25
Get the list of distribution certificates from app connect api
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?
Replies
1
Boosts
0
Views
402
Activity
Apr ’25
Create app in Appstore using AppStoreConnect API is giving an error.
Hello Apple Developer Team, I've followed the AppStoreConnect API documentation and created the following: I've created a API Key in App store > Integrations > Teams key, gave the role as admin. Created a valid JWT token When fetching the GET v1/apps, I can see the list of apps. Also I was able to make GET v1/users as well successfully. I've the valid bundle Id and capabilities enabled in the developer portal. Facing an issue while creating an app in App Store using AppStoreConnect API using POST call: This is my ruby script: response = api_request( method: :post, path: "/v1/apps", token: token, body: { data: { type: 'apps', attributes: { name: APP_NAME, primaryLocale: LOCALE, sku: "SKU#{Time.now.to_i}", bundleId: BUNDLE_ID, platform: 'IOS' } } } ) It gives me below error: { "errors": [ { "id": "09b465fc-316f-47b4-9bc3-9c340cb966aa", "status": "403", "code": "FORBIDDEN_ERROR", "title": "The given operation is not allowed", "detail": "The resource 'apps' does not allow 'CREATE'. Allowed operations are: GET_COLLECTION, GET_INSTANCE, UPDATE" } ] } Did anyone was able to successfully create the app in App Store via AppStoreConnect API? Could you please help me identify the root cause for the above issue and provide some inputs so that I could work on resolving them and move forward in the deployment process. Appreciate your help in reviewing this. Thank you, Santosh
Replies
0
Boosts
0
Views
228
Activity
Apr ’25
Requesting Code-Level Support: Node.js Script to Fetch US Education Apps with "Exam Prep" by Revenue
Hi Apple Developer Support, I’m working on a Node.js script to fetch all apps listed under the Education category and Reference subcategory from the US App Store, where the app name includes "exam prep". My goal is to list these apps in descending order of their earned revenue (including both paid apps and those with subscriptions). To proceed, I’m looking for guidance or code-level support on: Accessing App Store metadata programmatically via Apple-approved APIs. Filtering apps by category, subcategory, and keywords in the app name. Sorting the result set by revenue (paid and subscription earnings). Is there any recommended API or service (official or via App Store Connect) that I should be using to achieve this? Appreciate any direction, documentation, or sample code that can help. Thanks in advance!
Replies
0
Boosts
0
Views
139
Activity
Apr ’25
decode profileContent
Hi, I'm using the https://developer.apple.com/documentation/appstoreconnectapi/get-v1-profiles api to fetch our provisions profiles and decoding them using bash but it looks like the outputs also encoded in a other way, can someone help me fix my code? Many thanks! Example of the beginning of the output profileContent output: 01 *H 101 1 0 + �0"� *H ! !<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>AppIDName</key> .... Code: output=$(curl -X GET \ -H "Authorization: Bearer $jwt" \ -H "Content-Type: application/json" \ --globoff "https://api.appstoreconnect.apple.com/v1/profiles?fields[profiles]=name,profileContent,profileState") while read row; do name=$(echo -n "$row" | jq -r .attributes.name) profileState=$(echo -n "$row" | jq -r .attributes.profileState) profileContent=$(echo -n "$row" | jq -r .attributes.profileContent | base64 -d) done < <(echo "$output" | jq -c '.data[]')
Replies
2
Boosts
0
Views
126
Activity
Apr ’25
App Store Connect shows more data than salesreports API
We're using https://api.appstoreconnect.apple.com/v1/salesReports (https://developer.apple.com/documentation/appstoreconnectapi/get-v1-salesreports) to get the First-Time Downloads as can be seen in the App Store Connect per app. But from the API we only get data since March 2025 while in the App Store Connect data can be seen since November 2022. From the API response we read the Units for entries where 'Product Type Identifier' is 1 (https://developer.apple.com/help/app-store-connect/reference/product-type-identifiers/) per Apple Identifier. The results is for all apps as we expect, but for one app we only get data since March 2025. It is indeed the case that the app has been published in March, but the same id was in use since November 2022, under another vendor though (different vendorNumber, which we don't know). Is there any way to get the statistics from before March, like can be seen in the App Store Connect? Perhaps another way of calling salesReports or another API. We tried https://appstoreconnect.apple.com/analytics/api/v1/data/timeseries as that is the call happening in App Store Connect which over there is returning data prior to March 2025, but we couldn't get it to work nor find documentation about it. Or can we feed the old data so we would get it back from salesReports?
Replies
0
Boosts
0
Views
141
Activity
Apr ’25
How to Best Practices for Implementing In-App Purchases (IAP) in Mobile Apps and Backend Systems
Hello everyone, I’d like to ask for your input regarding best practices for implementing In-App Purchases (IAP) across both the frontend and backend. Here’s our current flow: -Frontend (Mobile) The user opens a specific page. We initiate a payment request using react-native-iap. After the user completes the payment, we send the purchase data (receipt) to our backend. Backend: Accept the purchase receipt from the app. Validate the receipt with Apple’s server. (GET https://api.storekit.itunes.apple.com/inApps/v1/transactions/{transactionId}) If the receipt is valid and the response indicates success, we mark the payment status as PAID. We store the transaction ID in our payment module. The Issue: We recently encountered a situation where Apple returned a valid receipt, so we marked the transaction as PAID. However, later we realized that the payment status was actually Pending. { transactionId: '70002676245699', originalTransactionId: '70002676245639', bundleId: '', productId: '', purchaseDate: 1745560404000, originalPurchaseDate: 1745560404000, quantity: 1, type: 'Consumable', inAppOwnershipType: 'PURCHASED', signedDate: 1745981078460, environment: 'Production', transactionReason: 'PURCHASE', storefront: 'SGP', storefrontId: '', price: 5000, currency: 'SGD', appTransactionId: '' } This raised a few questions: Does a Pending status always resolve to Paid, or is there a risk that Apple may later mark it as Failed or Unpaid? Is there a specific field in Apple's receipt response that reliably indicates whether the purchase is truly active? Should we hold off on granting access or product delivery until the status transitions from Pending to Paid? We’d really appreciate any insights or recommendations on how to handle this edge case to avoid granting access prematurely. Thanks in advance!
Replies
0
Boosts
0
Views
213
Activity
Apr ’25
App Store Connect Metrics via REST API
I hope this message finds you well. I’m reaching out to ask whether specific App Store Connect metrics available in the App Analytics dashboard can also be accessed via the App Store Connect REST API. I have reviewed the official API documentation, but I couldn’t find confirmation regarding the metrics listed below. Could you kindly clarify if the following metrics are available through the REST API? And if so, could you point me to the relevant endpoints or documentation? From the "Usage" group: Installations (Opt-in only) Active Devices Deletions (Uninstalls) From the "App Store" group: Impressions (Unique Devices) Product Page Views (Unique Devices) If these metrics are not available via the REST API, is there an alternative method to programmatically access or export them? Thank you very much in advance for your help and guidance.
Replies
2
Boosts
0
Views
229
Activity
May ’25
Apple Connect API
Hello, can any help to set a price change to any of our In-Apps programmaticly(C#). I'm have no problem to create the token and i get positive results for GET calls (like In-App purchase data or Apple PriceTemplates). My Get call is a simple HttpClient GetAsync(id) so I supposed I need a HttpClient PostAsync(url, content). The result is a "404 NotFound" which is no error shown for this call. I searched a lot to fix the error but I found nothing that is explaining this error. My content is created like this: var content = new StringContent(jsonmodel, Encoding.UTF8, "application/json"); My URL: https://api.appstoreconnect.apple.com/v1/inAppPriceSchedules My JsonModel: { "data": { "relationships": { "baseTerritory": { "data": { "id": "DEU", "type": "territories" } }, "inAppPurchase": { "data": { "id": "6448129561", "type": "inAppPurchases" } }, "manualPrices": { "data": [ { "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ", "type": "inAppPurchasePrices" } ] } }, "type": "inAppPurchases", "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ" }, "included": [ { "attributes": { "startDate": null, "endDate": null }, "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ", "relationships": { "inAppPurchasePricePoint": { "data": { "id": "eyJzIjoiNjQ0ODEyOTU2MSIsInQiOiJERVUiLCJwIjoiMTAxMjcifQ", "type": "inAppPurchasePricePoints" } }, "inAppPurchaseV2": { "data": { "id": "6448129561", "type": "inAppPurchases" } } }, "type": "inAppPurchasePrices" } ] } regards kas
Replies
0
Boosts
0
Views
104
Activity
May ’25
Creating Advanced AppClip Experiences Via API
I'm trying to programmatically create an Advanced AppClip Experience via the API. following the docs https://developer.apple.com/documentation/appstoreconnectapi/app-clips-and-app-clip-experiences I have created the header image. But when I try to create the experience I can not figure out a) how to create a localisationID to be included in the relationships object b) how to get the included object to be recognised Any one have experience or can offer help?
Replies
1
Boosts
0
Views
126
Activity
May ’25
I can't verify App Store Notification
I'm setting up App Store Notifications for my app. Having trouble verifying even the TEST notification, through. I'm generating JWT-token and sending it via Postman. I get a successful notification UUID as a response. But my Node.JS endpoint says it can't verify it. Here's the endpoint: const fs = require('fs'); const path = require('path'); const { SignedDataVerifier, Environment } = require('@apple/app-store-server-library'); module.exports = function (sqlexec) { function loadRootCAs() { // const gPath = path.resolve(__dirname, "AppleIncRootCertificate.cer"); const g3Path = path.resolve(__dirname, "AppleRootCA-G3.cer"); // const g2Path = path.resolve(__dirname, "AppleRootCA-G2.cer"); const loadedCerts = []; try { // loadedCerts.push(fs.readFileSync(gPath)); loadedCerts.push(fs.readFileSync(g3Path)); // loadedCerts.push(fs.readFileSync(g2Path)); if (loadedCerts.length === 0) { throw new Error("No Apple Root CA certificates were loaded."); } console.log("[APPLE NOTIFICATIONS2] Apple Root CA certificates loaded successfully."); return loadedCerts; } catch (error) { console.error("❌ CRITICAL: Error loading Apple Root CA certificate(s):", error.message); console.error("Ensure 'AppleRootCA-G3.cer' (and others if specified) are present at the expected path and readable."); throw new Error("Failed to load essential Apple Root CA certificates. Notification processing will fail."); } } const appleRootCAs = loadRootCAs(); const enableOnlineChecks = true; const environment = Environment.SANDBOX; const bundleId = "SomeBundleID"; const appAppleId = undefined; // Set if you're in PRODUCTION const verifier = new SignedDataVerifier( appleRootCAs, enableOnlineChecks, environment, bundleId, appAppleId ); router.post('/notifications_refund', async function (req, res) { const signedPayload = req.body.signedPayload; try { const notificationVerificationResult = await verifier.verifyAndDecodeNotification(signedPayload); if (!notificationVerificationResult.isValid) { console.error(`[APPLE NOTIFICATIONS2] Failed to verify notification. Status: ${notificationVerificationResult.verificationStatus}, Error: ${notificationVerificationResult.errorMessage || 'N/A'}`); return res.status(400).json({ status: "error", message: "Invalid notification signature or payload." }); } const decodedNotification = notificationVerificationResult.payload; const notificationType = decodedNotification.notificationType; const subtype = decodedNotification.subtype; if (notificationType === 'TEST') { console.log(`[APPLE NOTIFICATIONS2] Received TEST notification. Subtype: ${subtype}`); // The TEST notification's data.signedTransactionInfo is a JWS representing a sample transaction. } else if (notificationType === 'REFUND') { console.log(`[APPLE NOTIFICATIONS2] Received REFUND notification. Subtype: ${subtype}`); } else { console.log(`[APPLE NOTIFICATIONS2] Received notificationType: ${notificationType}, Subtype: ${subtype}. Skipping non-refund/test type for this endpoint.`); return res.status(200).json({ status: "success", message: "Notification received, but not a type processed by this refund endpoint." }); } // Ensure data and signedTransactionInfo exist if (!decodedNotification.data || !decodedNotification.data.signedTransactionInfo) { console.error("[APPLE NOTIFICATIONS2] Notification payload is missing data or signedTransactionInfo."); return res.status(400).json({ status: "error", message: "Notification missing transaction info." }); } const transactionInfoJWS = decodedNotification.data.signedTransactionInfo; const transactionVerificationResult = await verifier.verifyAndDecodeTransaction(transactionInfoJWS); if (!transactionVerificationResult.isValid) { console.error(`[APPLE NOTIFICATIONS2] Failed to verify signedTransactionInfo. Status: ${transactionVerificationResult.verificationStatus}, Error: ${transactionVerificationResult.errorMessage || 'N/A'}`); return res.status(400).json({ status: "error", message: "Invalid signedTransactionInfo in notification." }); } const verifiedTransactionPayload = transactionVerificationResult.payload; const transactionId = verifiedTransactionPayload.originalTransactionId || verifiedTransactionPayload.transactionId; console.log(`[APPLE NOTIFICATIONS2] Successfully decoded Transaction ID: ${transactionId} for notification type ${notificationType}`); // This is where my refund logic starts in case the notif is refund, but fow now I'm just trying to verify a TEST notif return res.status(200).json({ status: "success", message: "Refund (or TEST) notification processed successfully and validated." }); } catch (error) { console.error("[APPLE NOTIFICATIONS2] Critical error processing notification:", error); // Check if the error is from the verifier or elsewhere if (error.name === 'SignedDataVerificationError') { // Example, check actual error type from library return res.status(400).json({status: "error", message: `Notification verification failed: ${error.message}`}); } return res.status(500).json({ status: "error", message: "Failed to process notification due to an internal server error." }); } }); return router; }; I tried different root certs, only G3 works, other two give errors. Also tried adding G3 intermediate (WWDRCAG3), but it doesn't seem to help. What am I doing wrong?
Replies
0
Boosts
0
Views
71
Activity
May ’25
App Store Analytics API Reports
Hi everyone, I’m new here. I’m working with the App Store Connect (ASC) Analytics API and I have some questions about how to retrieve historical data for downloads and in-app purchases. I’ve created two types of reports: 1. ONGOING: Retrieves current and recent data. 2. ONE_TIME_SNAPSHOT: Supposedly retrieves historical data. I am specifically interested in the Detailed versions: • App Store Downloads Detailed • App Store Purchases Detailed What's my problem? 1. The ONGOING report brings instances with data from the last few days, which seems correct for App Downloads. But not with Purchases, it brings just a few random days and I'm not sure about the granularity. 2. The ONE_TIME_SNAPSHOT report, however, retrieves instances with data from specific days, but the selection of these days appears to be random. I can’t figure out the criteria behind it. Does anyone know what the selection criteria are for the days that appear in the ONE_TIME_SNAPSHOT report? Is it possible to configure the date range for this type of report? Why are some historical dates available while others are not? Is there a way to ensure that the ONE_TIME_SNAPSHOT report brings data from all days within a specified range? Any advice or insights would be greatly appreciated! Thanks in advance!
Replies
0
Boosts
0
Views
243
Activity
May ’25
Retrieving each user’s “last login” timestamp via the App Store Connect API – is it possible?
Hello everyone, I’m building a custom tool that uses the App Store Connect API (v1) to manage my team’s users. I can successfully list all users with: GET https://api.appstoreconnect.apple.com/v1/users …but the JSON response only includes fields like firstName, lastName, email, allAppsVisible, provisioningAllowed, and roles. There is no lastLogin or timestamp field anywhere in the User object: { "data": [ { "id": "USER_ID", "type": "users", "attributes": { "firstName": "mohit", "lastName": "tiwari", "email": "", "allAppsVisible": false, "provisioningAllowed": false }, "relationships": { … } }, … ] } My main question is: How can I retrieve each user’s “last login” timestamp via the App Store Connect API? Is this even possible with the current endpoints? If it isn’t exposed, has Apple any plans to add this? Or are there any recommended workarounds—perhaps via audit logs or another API—to track when each user last accessed App Store Connect? Thanks in advance for your guidance and any code/endpoint examples you can share!
Replies
0
Boosts
0
Views
124
Activity
May ’25
API permison
Hello, I am thinking of developing a parental control app but I do not know if I need to request the api for using "Time Screen API". In positive case, where it should be? Is there anyway to use this for educational centers? Not just for families? Kind regards.
Replies
1
Boosts
0
Views
117
Activity
Jun ’25
App Store Connect API: 'UNIVERSAL' is not a valid value for the attribute 'platform'
Hello, We are encountering an issue when using the App Store Connect API to create a bundle ID via the endpoint: POST https://api.appstoreconnect.apple.com/v1/bundleIds In our request, we specify the platform value "UNIVERSAL", which according to the official documentation is a valid value: BundleIdPlatform documentation However, the API now returns the following error response: { "errors": [ { "code": "ENTITY_ERROR.ATTRIBUTE.TYPE", "detail": "'UNIVERSAL' is not a valid value for the attribute 'platform'. Expected one of: 'IOS', 'MAC_OS'", "status": "409", "title": "An attribute in the provided entity has the wrong type" } ] } According to the documentation, the platform attribute accepts the following values: IOS, MAC_OS and UNIVERSAL. It appears that UNIVERSAL is no longer accepted even though it is still listed as a valid option. Has support for UNIVERSAL been deprecated or changed recently? If so, what is the current recommended way to create bundle IDs that are intended for multiple platforms? Any clarification would be greatly appreciated. Thank you!
Replies
0
Boosts
0
Views
162
Activity
Jun ’25
DEVELOPER_ID_APPLICATION_G2 is not recognized by ASC API
Hi, ASC API call rejects DEVELOPER_ID_APPLICATION_G2 and does not recognize it, even though it is listed as a valid certificateType in the docs: https://developer.apple.com/documentation/appstoreconnectapi/get-v1-certificates. If it was removed from the certificate list, then why Apple forces to choose the G2 type when creating a DEVELOPER_ID_APPLICATION certificate manually in the Apple Developer account. Can someone from Apple support please check it as it is a contradictory behavior and is a blocker.
Replies
2
Boosts
0
Views
151
Activity
Jun ’25
Customer review forbidden error message despite successful auth
Hi, I am seeking assistance and feedback on the below post on feedback assistant. FB18169176 (Customer review API forbidden error) I am calling this endpoint in a python script: https://api.appstoreconnect.apple.com/v1/apps/6450458286/customerReviews?limit=200&sort=-createdDate I can verify that I am getting a valid JWT token. An example is on the feedback link. Yet I am getting this error: { "errors" : [ { "id" : "eda3b456-9aa9-47bd-8736-439db0c73545", "status" : "403", "code" : "FORBIDDEN_ERROR", "title" : "This request is forbidden for security reasons", "detail" : "The API key in use does not allow this request" } ] } Please advise why this is the case, and please assist as this information is needed urgently. Thank you.
Replies
0
Boosts
0
Views
69
Activity
Jun ’25
External Purchase: status 401
Good morning, I am configuring in backend the sending of reports regarding purchases made in app with external platform (Stripe) as per documentation. To be clear I am talking about ExternalPurchase. However, when I make the call it returns "Apple responded with status 401". I verified the token on jwt.io as per documentation and it is working. I don't understand where I am going wrong. Below I share the code with you: const express = require("express"); const bodyParser = require("body-parser"); const jwt = require("jsonwebtoken"); const fs = require("fs"); const app = express(); const https = require("https"); const APPLE_KEY_ID = "XXXXX"; const APPLE_ISSUER_ID = "xxx-xxx-xxx-xx-xxxxxx"; const APPLE_PRIVATE_KEY = fs.readFileSync("AuthKey_xxxxx.p8", "utf8"); const APPLE_AUDIENCE = "appstoreconnect-v1"; function generateAppleJwt() { const now = Math.floor(Date.now() / 1000); const payload = { iss: APPLE_ISSUER_ID, iat: now, exp: now + (5 * 60), aud: APPLE_AUDIENCE }; return jwt.sign(payload, APPLE_PRIVATE_KEY, { algorithm: "ES256", header: { alg: "ES256", kid: APPLE_KEY_ID, typ: "JWT" } }); } app.post('/webhook', bodyParser.json({ type: 'application/json' }), async (req, res) => { let eventType = req.body.type; const relevantEvents = [ "invoice.paid" ]; if (relevantEvents.includes(eventType)) { try { const data= req.body.data; const platform = data.object.subscription_details.metadata.platform; if (platform === "IOS") { const token = generateAppleJwt(); const applePayload = { appAppleId: "xxxx", bundleId: 'com.xxx.xxx.test', externalPurchaseId: data.object.id, purchaseTime: new Date(data.object.created * 1000).toISOString(), purchaseAmount: { amount: (data.object.total / 100).toFixed(2), currencyCode: data.object.currency.toUpperCase() }, purchaseLocation: { isoCountryCode: "IT" } }; const jsonString = JSON.stringify(applePayload); const agent = new https.Agent({ keepAlive: false }); const response = await fetch( "https://api.storekit-sandbox.apple.com/externalPurchase/v1/reports", { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", "Accept-Encoding": "identity", }, body: JSON.stringify(applePayload), } ); if (!response.ok) { const errorText = await response.text(); throw new Error( `Apple responded with status ${response.status}: ${errorText}` ); } console.log("✅ Notifica inviata ad Apple con successo"); } else { if(!canSendNotification){ console.log("Non è una Sub. Nessuna notifica inviata."); }else{ console.log("Customer non iOS. Nessuna notifica inviata."); } } } catch (err) { console.error("Errore durante l’invio ad Apple:"); if (err.response) { console.error("Status:", err.response.status); console.error("Headers:", err.response.headers); console.error("Data:", err.response.data); } else { console.error("Message:", err.message); } } } res.status(200).send("OK"); }); exports.checkSubStripe = functions.https.onRequest(app);
Replies
0
Boosts
0
Views
126
Activity
Jun ’25