Easy Apple App Store Connect access with Perl
Tags: perl, apple
Published: 2023-08-06 21:37:32

I develop iOS apps as a hobby (mainly [Xasteria weather](https://apps.apple.com/us/app/xasteria-astronomy-weather/id985030722) and the astronomy app [Polar Scope Align](https://apps.apple.com/us/app/polar-scope-align-pro/id970161373)), which means I have to deal with Apple's App Store Connect site to manage them.

Not sure how Apple does it, but the site is usually extremely slow, especially on the pages that require async fetching data (e.g. sales, beta versions, reviews) - which is the majority of your page views. Given the fact that there are no notifications / alerting for things like user reviews or beta tester feedback, you'd have to remember to regularly visit those pages for every app, which can actually take a few minutes of your time for a handful or more of apps.

Thankfully, there are some options if you want to make things like that easy. You could use one of the 3rd party sites that access your App Store accounts for you (but you have to trust them with access, which is not something I'd be willing to do), or you can use the API Apple provides to script your own automation. I do the latter and recently thought it might be helpful to package and release the module I use to do that in Perl: it's now on CPAN as [Apple::AppStoreConnect](https://metacpan.org/pod/Apple::AppStoreConnect).

You can read up the [documentation for the App Store Connect API](https://developer.apple.com/documentation/appstoreconnectapi) to see what's possible and if you can do some Perl you can use the module to make things easy. I'll even add a quick guide below with everything you need and include a quick example script.


### App Store Connect key ###

The first thing you will need is an App Store Connect API key. You get it from the App Store Connect [portal](https://appstoreconnect.apple.com/):

- Go to Users and Access, Keys, [App Store Connect API](https://appstoreconnect.apple.com/access/api) and create a new key selecting the [role](https://developer.apple.com/help/app-store-connect/reference/role-permissions) depending on the permissions you wish.
- Download the key (careful, you'll only be able to download it once), which will be in the form of `AuthKey_YOURKEYID.p8`.
- The key is in the PKCS8 format, which you'll need to convert to the PEM format. On a Mac you can convert it simply:
```
openssl pkcs8 -nocrypt -in AuthKey_YOURKEYID.p8 -out AuthKey_YOURKEYID.pem
```
- Locate the **issuer ID** string above the list of keys on the same page (e.g. `57246542-96fe-1a63-e053-0824d011072a`).


### Accessing the API with Apple::AppStoreConnect ###

Make sure you have the [Apple::AppStoreConnect](https://metacpan.org/pod/Apple::AppStoreConnect) module installed. Like most Perl modules, the installation normally involves something like:
```
cpanm Apple::AppStoreConnect
```
Then, we can create a connection object using the key data we got previously and print the raw JSON response of the "List apps" endpoint:

```perl

use Apple::AppStoreConnect;

my $asc = Apple::AppStoreConnect->new(
    issuer   => "57246542-96fe-1a63-e053-0824d011072a",
    key_id   => "YOURKEYID",
    key_file => "AuthKey_YOURKEYID.pem",
);

my $json = asc->get(url=>"apps",raw=>1);

print $json;
```

### Full example getting latest customer reviews  ###

Here is a complete example for getting the latest customer reviews across all your apps that you can run on Mac/Linux:

```perl
#!/usr/bin/env perl

use strict;
use warnings;
use v5.20;

use Apple::AppStoreConnect;

# Print unicode chars in reviews
binmode (STDOUT, ":utf8");

my $asc = Apple::AppStoreConnect->new(
    issuer   => "YOUR-ISSUER-ID",
    key_id   => "YOURKEYID",
    key_file => "AuthKey_YOURKEYID.pem",
);

# Get all apps
my $apps = $asc->get_apps();
my %rev;

foreach my $id (keys %$apps) {
    # Get the 10 most recent reviews of each app
    my $res = $asc->get_apps(
        id     => $id,
        path   => "customerReviews",
        params => {
            sort  => "-createdDate",
            limit => 10
        }
    );
    # Add the app name to the review details
    $res->{$_}->{app_name} = $apps->{$id}->{name} for keys %$res;
    %rev = (%rev, %$res);
}

# print 20 reviews from newest to oldest
my $cnt = 1;
foreach my $r (sort {$b->{createdDate} cmp $a->{createdDate}} values %rev) {
    # Print date, app name, rating, territory, review title and body
    say "$r->{createdDate} $r->{app_name}";
    say "Rating:$r->{rating} Territory:$r->{territory}";
    say "Title:$r->{title}";
    say "$r->{body}\n";
    last if ++$cnt > 20;
} 
```