Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

No access to build artifacts in Xcode Cloud

Lost access to all the build artifacts in Xcode Cloud.

When I try downloading any build artifact from the web page I'm getting:

{"message":"You are not authorized to access this team’s resources."}

Same attempt from Xcode just crashes the app. Started to happen today or some time yesterday, after 12am EST.

Answered by DTS Engineer in 814785022

@beetee , @Manulpz , and @sergiy_s_idv

The issue is resolved. Please try again.

Encountering the same issues here. First time using XCode Cloud yesterday, not a great first experience.

Thought I'd share my solution here for anyone experiencing the same issues and have experience with Python. I made some simple scripts that can be used to manually extract out the download URLs of each artifact.

# generate_token.py
import jwt
import time
from datetime import datetime, timedelta

# Define your App Store Connect API credentials
KEY_ID = '________'
ISSUER_ID = '________'
PRIVATE_KEY_PATH = '________.p8'

with open(PRIVATE_KEY_PATH, 'r') as key_file:
    private_key = key_file.read()

def generate_token():
    headers = {
        "alg": "ES256",
        "kid": KEY_ID,
        "typ": "JWT"
    }
    payload = {
        "iss": ISSUER_ID,
        "exp": int(time.time()) + 20 * 60,  # Token expiration in 20 minutes
        "aud": "appstoreconnect-v1"
    }
    token = jwt.encode(payload, private_key, algorithm="ES256", headers=headers)
    return token
# fetch_workflows.py
import time
import requests
from datetime import datetime, timedelta

def fetch_products(token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciProducts"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])
  
def fetch_workflows(product_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciProducts/{product_id}/workflows"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    from generate_token import generate_token
    products = fetch_products(generate_token())
    print(f"Found {len(products)} products")
    for product in products:
        print(f"{product['attributes']['name']} ({product['attributes']['productType']}): {product['id']}")

        workflows = fetch_workflows(product['id'], generate_token())
        print(f"Found {len(workflows)} workflows")
        for workflow in workflows:
            print(f"{workflow['attributes']['name']}: {workflow['id']}")
# fetch_build_runs.py
import time
import requests
from datetime import datetime, timedelta

# Fetch all build runs for the specified workflow
def fetch_build_runs(workflow_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciWorkflows/{workflow_id}/buildRuns"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    params = {
        "limit": 200  # Adjust the limit as needed; 200 is the maximum
    }
    
    response = requests.get(url, headers=headers, params=params)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    import argparse
    from generate_token import generate_token
    parser = argparse.ArgumentParser(description="Fetch all build runs for a given workflow ID.")
    parser.add_argument("workflow_id", help="The workflow ID for which to fetch build runs for.")
    args = parser.parse_args()

    build_runs = fetch_build_runs(args.workflow_id, generate_token())
    print(f"Found {len(build_runs)} runs for workflow {args.workflow_id}")
    for build_run in build_runs:
        print(f"Build {build_run['attributes']['number']}: {build_run['id']}")
# fetch_build_actions.py
import time
import requests
from datetime import datetime, timedelta

def fetch_build_actions(build_run_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciBuildRuns/{build_run_id}/actions"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    import argparse
    from generate_token import generate_token
    parser = argparse.ArgumentParser(description="Fetch all build actions for a given build run ID.")
    parser.add_argument("build_run_id", help="The build run ID for which to fetch build actions from")
    args = parser.parse_args()

    build_actions = fetch_build_actions(args.build_run_id, generate_token())
    print(f"Found {len(build_actions)} actions for run {args.build_run_id}")
    for build_action in build_actions:
        print(f"{build_action['attributes']['name']}: {build_action['id']}")
# fetch_artifacts.py
import time
import requests
from datetime import datetime, timedelta

def fetch_artifacts(build_action_id, token):
    url = f"https://api.appstoreconnect.apple.com/v1/ciBuildActions/{build_action_id}/artifacts"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    
    response = requests.get(url, headers=headers)
    response.raise_for_status()
    return response.json().get("data", [])

if __name__ == "__main__":
    import argparse
    from generate_token import generate_token
    parser = argparse.ArgumentParser(description="Fetch all artifacts for a given build action ID.")
    parser.add_argument("build_action_id", help="The build action ID for which to fetch artifacts.")
    args = parser.parse_args()

    artifacts = fetch_artifacts(args.build_action_id, generate_token())
    print(f"Found {len(artifacts)} artifacts for action {args.build_action_id}")
    for artifact in artifacts:
        print(f"{artifact['attributes']['fileName']}: {artifact['attributes']['downloadUrl']}")

Note that you will need to pip install cryptography pyjwt requests.

Same here. I just tried today. I had access to artifacts last week but not today.

We are looking into the issue. Thank you for your patience.

Accepted Answer

@beetee , @Manulpz , and @sergiy_s_idv

The issue is resolved. Please try again.

No access to build artifacts in Xcode Cloud
 
 
Q