Appstoreconnect API redirecting to a different endpoint

Hi all,

I'm writing this because I'm pretty confused about the behaviour of the API, and maybe someone had the same issue.

I'm trying to query this endpoint and using this code to sign the JWT token:

def generate_token(issuer_id, key_id, private_key_content):

    token_data = jwt.encode(
        {
            'iss': issuer_id,
            'aud': 'appstoreconnect-v1',
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=15)
        },
        private_key_content,
        algorithm='ES256',
        headers={
            'kid': key_id
        }
    )
    return token_data

secret = b'''MY SECRET KEY FILE HERE'''

token = generate_token("MY ISSUER ID HERE", "MY KEY ID HERE", secret)

Once I have the token I used to query the endpoint using requests like this:

response_sales = requests.get(f'https://appstoreconnect.apple.com/analytics/api/v1/salesReports?frequency=DAILY&reportSubType=DETAILED&reportType=SALES&vendorNumber={my_vendor_id}',
                        headers={'Authorization': f'Bearer {token}'})

And the output of my requests is something like that:

response_sales.url
https://appstoreconnect.apple.com/login?targetUrl=%2Fanalytics%2Fapi%2Fv1%2FsalesReports%3Ffrequency%3DDAILY%26reportSubType%3DDETAILED%26reportType%3DSALES%26vendorNumber%3DMY_VENDOR_NUMBER_HERE&authResult=FAILED

and

response_sales.text
'<!DOCTYPE html>\n<html ng-controller="pageWrapperController as wrapper">\n<head>\n    <meta charset="utf-8" />\n    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />\n    <title ng-bind="title"></title>\n    <meta name="description" content="" />\n    <meta name="viewport" content="width=device-width, initial-scale=1" />\n    <!-- <meta name="apple-itunes-app" content="app-id=376771144, affiliate-data=ct=itcweblogin&pt=2003"/> -->\n    <meta ng-if="isAsc" name="apple-itunes-app" content="app-id=1234793120, affiliate-data=ct=ascweblogin&pt=2003" />\n    <meta http-equiv="CACHE-CONTROL" content="no-cache, no-store, must-revalidate">\n    <META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">\n    <META HTTP-EQUIV="EXPIRES" CONTENT="0">\n\n    <base href="/" />\n\n    <link rel="stylesheet" type="text/css" href="https://www.apple.com/wss/fonts?families=SF+Pro,v1|SF+Pro+Icons,v1" type="text/css" media="all">\n    <link rel="stylesheet" type="text/css" href="/static/vendors.1668720955944.css" />\n    <link rel="stylesheet" href="/static/vendor/itc-header-angular.all.min.css" />\n    <link rel="stylesheet" type="text/css" href="/static/itunesconnect.1668720955944.css" />\n\n    <script>\n        window.global_itc_path = \'/WebObjects/iTunesConnect.woa\';\n    </script>\n\n    <script src="/static/vendors.1668720955944.js"></script>\n    <script src="/static/itunesconnect.1668720955944.js"></script>\n</head>\n\n<body ng-class="wrapperClasses">\n\n    <div id="pageWrapper" ng-show="wrapper.locReady">\n\n        <div id="header">\n            <itc-header logo="itcHeaderLogo" components="itcHeaderComponents"></itc-header>\n            <div id="developer-header-text" ng-bind-html="wrapper.devHeaderWelcome" ng-show="wrapper.showDevHeaderWelcome"></div>\n        </div>\n\n        <div id="view-wrapper" class="flexcol" ui-view></div>\n\n        <footer id="footer" ng-if="includeDevFooter" class="footer">\n            <div class="footer-content">\n                <section class="footer-mini">\n                    <div class="footer-mini-shop footer-mini-news" ng-bind-html="\'ITC.Developer.Login.Footer.NewsText\' | l10n"></div>\n                    <div class="footer-mini-legal">\n                        <div class="footer-mini-legal-copyright" ng-bind-html="(wrapper.footerConfig.text.copyright + \' \' + wrapper.footerConfig.text.year + \' \' + wrapper.footerConfig.text.rights)"></div>\n                        <div class="footer-mini-legal-links">\n                            <a class="footer-mini-legal-link" ng-repeat="link in wrapper.footerConfig.links" href="{{ link.url }}" ng-bind-html="link.text" target="_blank"></a>\n                        </div>\n                    </div>\n                </section>\n            </div>\n        </footer>\n\n        <div id="footer" ng-if="includeFooter" class="tb-grid tb-grid--no-gutters new-footer" ng-class="{\'dark-style\': !darkFooter, \'not-logged-in\': !userProfile.userIsAuthenticated}">\n\n            <div class="tb-row">\n\n                <div class="tb-col--small-24">\n\n                    <a href="http://www.apple.com" class="no-text ico-apple">Apple.com</a>\n\n                    <itc-footer ng-if="wrapper.locReady" config="wrapper.footerConfig"></itc-footer>\n                </div>\n\n            </div>\n        </div>\n\n    </div>\n\n    <div id="pageSpinner" tidbits-spinner="wrapper.pageSpinner" displayed="wrapper.pageSpinnerDisplayed"></div>\n</body>\n</html>

I check some other endpoints and everything works ok, so I assume this is not an issue related to my key (it has assigned the admin and finance role)

Anyone has a clue of why this is happening and how to solve it?

Thank in advance :)

Hey @Alberto_C_Solo,

Thanks so much for positing this question on the forums!

After reviewing the code that you have shared (thank you for doing so!), I am not sure if it could be this simple, but it looks like the URL that you are using when interacting with the App Store Connect API could be wrong. Below is what you have listed in your code example above:

https://appstoreconnect.apple.com/analytics/api/v1/salesReports

Below is the URL that I am using when interacting with the App Store Connect API and I am not running into issues while retrieving sales data.

https://api.appstoreconnect.apple.com/v1/salesReports

I did test this on my side and when I hit the API with the URL that you are using I am encountering the same error.

Would it be possible to test using the different base URL and determining if this resolves your issue?

Hopefully this helps and happy coding!

Appstoreconnect API redirecting to a different endpoint
 
 
Q