Skip to content

Instantly share code, notes, and snippets.

@corrieriluca
Last active March 28, 2024 23:55
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save corrieriluca/3c9f062401582dad83013d7363741b0c to your computer and use it in GitHub Desktop.
Save corrieriluca/3c9f062401582dad83013d7363741b0c to your computer and use it in GitHub Desktop.
Connection to the App Store Connect API using Python3

How to connect to the App Store Connect API using Python3

You will need the requests and authlib packages. Just run :

$ pip install requests authlib

Then you need to generate an API Key from the App Store Connect portal (https://developer.apple.com/documentation/appstoreconnectapi/creating_api_keys_for_app_store_connect_api).

In the Python code below, replace the values of KEY_ID, ISSUER_ID and PATH_TO_KEY with your own.

You can change the URL of the request you want to make with the URL variable.

Finally, if you have some query parameters to pass in, use the params parameter of requests.get() (or requests.post()).

import requests, time, json
from authlib.jose import jwt
KEY_ID = "XXXXXXXXXX"
ISSUER_ID = "XXXXXX-XXXXXXX-XXXXXX-XXXXXXX"
EXPIRATION_TIME = int(round(time.time() + (20.0 * 60.0))) # 20 minutes timestamp
PATH_TO_KEY = 'path/to/your/key.p8'
with open(PATH_TO_KEY, 'r') as f:
PRIVATE_KEY = f.read()
header = {
"alg": "ES256",
"kid": KEY_ID,
"typ": "JWT"
}
payload = {
"iss": ISSUER_ID,
"exp": EXPIRATION_TIME,
"aud": "appstoreconnect-v1"
}
# Create the JWT
token = jwt.encode(header, payload, PRIVATE_KEY)
# API Request
JWT = 'Bearer ' + token.decode()
URL = 'https://api.appstoreconnect.apple.com/v1/users'
HEAD = {'Authorization': JWT}
r = requests.get(URL, params={'limit': 200}, headers=HEAD)
# Write the response in a pretty printed JSON file
with open('output.json', 'w') as out:
out.write(json.dumps(r.json(), indent=4))
@NathanDotTo
Copy link

Thank you 👍

@slikk66
Copy link

slikk66 commented Sep 17, 2020

just what I was looking for - thank you 👋

@boralprophecy
Copy link

Thank you :)

@ilyosbekkk
Copy link

It is returning 401 error code

@Mgmaplus
Copy link

this seems better than reporter thxs!

@PrekshyaBasnet
Copy link

Thank you so much 🤗

@veronika-petrenko
Copy link

thank you!!

@callanmurphy
Copy link

Amazing thank you

@alk0v
Copy link

alk0v commented Jul 13, 2021

Hi. I used this example early and it had worked fine, but today I faced with "Error 401". When I tried to use the same token in the curl, it has worked too. The solution is to change the expiration time to 19 min (thanks to my colleague Oleh for this solution)
EXPIRATION_TIME = int(round(time.time() + (19.0 * 60.0))) # 19 minutes timestamp

or just add small delay
time.sleep(5)
before request.

@da-eos
Copy link

da-eos commented Aug 20, 2021

Hi, I set exp time 19 min, but I response 401 Error.
time.sleep(5) didn't help me.
If you know how to solve this problem, it will be nice..

@da-eos
Copy link

da-eos commented Aug 26, 2021

If you have the same problem 401 ->
check your jwt encode in https://jwt.io, just paste in form Encoded your token after jwt.encode. You must see correct headers and payload. It helps me to find error.

@yangyubo
Copy link

yangyubo commented Jan 17, 2022

Thank you very much for the sample code, I rewrote this sample with Applaud:

import os
from applaud.connection import Connection

KEY_ID = "XXXXXXXXXX"
ISSUER_ID = "XXXXXX-XXXXXXX-XXXXXX-XXXXXXX"
PATH_TO_KEY = os.path.expanduser('path/to/your/key.p8')

with open(PATH_TO_KEY, 'r') as f:
    PRIVATE_KEY = f.read()

# Create the Connection
connection = Connection(ISSUER_ID, KEY_ID, PRIVATE_KEY)
# API Request
r = connection.users().limit(10).get()

# Print user names
for user in r.data:
    print(user.attributes.username, user.attributes.first_name, user.attributes.last_name)

Applaud handles the details of JWT, you don't have to worry about expiration time. You can find the fork here: How to connect to the App Store Connect API using Python3 and Applaud

@nelsonspbr
Copy link

Thank you. I was getting 401 NOT_AUTHORIZED, changing expiration to 10 minutes fixed it.

@tanuj2207
Copy link

Where to find "path_to_key" ?
Anyone please reply fast is possible!!!

Thankyou in Advanced

@sompodsign
Copy link

@tanuj2207 You can get it from app store key section.

@Jana1977
Copy link

getting this error
JWT = 'Bearer ' + token.decode()
AttributeError: 'str' object has no attribute 'decode'

@Jana1977
Copy link

anyone ran into this error in the past ?

@alex-childish
Copy link

Thank you! Apple also seems to require "bid" (bundle id) param for JWT payload now - at least it kept giving me 401 until I added it. Here's how their current payload example looks like:

{
  "iss": "57246542-96fe-1a63e053-0824d011072a",
  "iat": 1623085200,
  "exp": 1623086400,
  "aud": "appstoreconnect-v1",
  "bid": "com.example.testbundleid2021"
}

@divyanshustaq
Copy link

Hi @alex-childish,

where did you get "bid"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment