A simplfied library for Node.js 10+ for accessing Apple's App Store Connect API, written in TypeScript.
The module is quite new, so issues and pull requests are very welcome :-)
Execute the following command from your project folder, where your package.json file is stored:
npm install --save @egodigital/appstore-connectimport * as fs from 'fs';
import { Client as AppStoreConnectClient, DownloadSalesReportFrequency } from '@egodigital/appstore-connect';
const PRIVATE_KEY = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const CLIENT = AppStoreConnectClient.create({
apiKey: '<YOUR-API-KEY>', // s. https://appstoreconnect.apple.com/access/api
issuerId: '<YOUR-ISSUER-ID>', // s. https://appstoreconnect.apple.com/access/api
privateKey: PRIVATE_KEY,
});
const SUMMARY = await CLIENT.getAppDownloads({
frequency: DownloadSalesReportFrequency.Weekly,
vendorId: '<YOUR-VENDOR-ID>', // s. https://appstoreconnect.apple.com/itc/payments_and_financial_reports
});
console.log(
SUMMARY
);import * as fs from 'fs';
import {BuildPlatformType, BuildProcessingState, ClientOptions, Client} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const marketingVersion = "1.0.25";
const buildNumber = 1;
try {
await client.waitForBuildProcessingToComplete(appId, BuildPlatformType.IOS, marketingVersion, buildNumber, {
pollIntervalInSeconds: 10,
// If build status is not valid wait 8 minutes
// Useful if calling this script directly after ipa was uploaded in order to not use up daily rate limit
initialDelayInSeconds: 60 * 8,
maxTries: 3,
onPollCallback: (state: BuildProcessingState, tries: number) => {
console.log(`Waiting for build processing to complete. Got status: ${state}. Tries: ${tries}`);
}
});
console.log("I'm done!");
process.exit(0);
}catch (e){
console.log("I failed");
console.log(e.message);
process.exit(1);
}
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const appStoreVersion = "1.0.25";
await client.createVersion(appId, appStoreVersion, PlatformType.IOS, {
copyright: "John Doe, Inc",
});
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const appStoreVersion = "1.0.25";
await client.ensureVersionExists(appId, appStoreVersion, PlatformType.IOS, {
createOptions: {
copyright: "John Doe, Inc",
},
// Updates any unreleased version to have the provided version
// This is useful in case you want to change the version you are planning to release since apple
// does not allow you to have multiple unreleased (pending) versions
// Only the version number will be updated. None of the create options will be used to update the existing version.
updateVersionStringIfUnreleasedVersionExists: true
});
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const appStoreVersion = "1.0.25";
const buildId = "7935ef82-4acf-11eb-b378-0242ac130002";
await client.attachBuildIdToVersion(appId, appStoreVersion, PlatformType.IOS, buildId)
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
// Not the same as the build pre-release version. Also referred to as the version string
const appStoreVersion = "1.0.25";
// Also referred to as pre-release version
const buildMarketingVersion = "1.0.25";
// Also referred to as the build version
const buildNumber = 2;
const versionId = await client.getVersionId(appId, appStoreVersion, PlatformType.IOS);
const buildId = await client.getBuildId(appId, buildMarketingVersion, PlatformType.IOS, buildNumber);
await client.attachBuildIdToVersionByVersionId(versionId, buildId);
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const version = "1.0.25";
const buildNumber = 2;
const groupId = "917ed9fe-4ada-11eb-b378-0242ac130002";
await client.addBuildToExternalGroupByGroupId(appId, version, PlatformType.IOS, buildNumber, groupId, {
notifyBetaTestersThereIsANewBuild: true
});
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const version = "1.0.25";
await client.submitForReview(appId, version, PlatformType.IOS);
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});import * as fs from 'fs';
import {Client, ClientOptions, PlatformType, SubmitForReviewOptions, ReleaseType} from '@egodigital/appstore-connect';
const privateKey = fs.readFileSync(
'/path/to/your/p8/file' // downloaded from https://appstoreconnect.apple.com/access/api
);
const clientOptions: ClientOptions = {
apiKey: "<YOUR-API-KEY>",
issuerId: "<YOUR-ISSUER-ID>",
privateKey
}
const client = Client.create(clientOptions);
const run = async () => {
const appId = 1543000000;
const version = "1.0.25";
const options: SubmitForReviewOptions = {
autoCreateVersion: true,
autoreleaseOnApproval: true,
autoAttachBuildId: "7935ef82-4acf-11eb-b378-0242ac130002",
releaseNotes: {
lang: 'en-CA',
text: 'Awesome new features. P.S. We love Canada!'
},
reviewDetailAttributes: {
contactEmail: 'imaspy@gmail.com',
contactFirstName: 'Jason',
contactLastName: 'Bourne',
contactPhone: '786-255-5555',
demoAccountName: 'mrusername',
demoAccountPassword: 'hello world',
demoAccountRequired: true,
notes: 'Shake the screen to start the demo mode'
},
versionAttributes: {
copyright: 'Spy Corp',
earliestReleaseDate: '2020-12-31T17:35:28.603Z',
releaseType: ReleaseType.SCHEDULED,
usesIdfa: false,
versionString: version,
downloadable: true
},
localizations: [
{
lang: 'en-US',
attributes: {
description: 'The best app of all time',
keywords: 'best,app,ever',
marketingUrl: 'https://spygear.com/app',
promotionalText: 'Spy on anyone with one simple app',
supportUrl: 'https://spygear.com/support',
whatsNew: 'Awesome new features for US users'
}
}
]
}
await client.submitForReview(appId, version, PlatformType.IOS, options);
}
run().then().catch((e: Error) => {
console.error(`Error: ${e.message}`);
console.debug(`Stack: ${e.stack}`);
process.exit(1);
});Additional API documentation can be found here.