When you create a new version of your app in App Store Connect, you might also need to upload new assets like screenshots or previews for the App Store. You can do this manually on the App Store Connect website, but if you have a lot of localizations to support and your assets change often across versions, this can be a tedious, error-prone, and time-consuming process.
Thankfully, you can automate this process using the App Store Connect API, which has a set of endpoints tailored for uploading media such as screenshots and previews. Unfortunately, using these endpoints is not straightforward and they require numerous steps that I will cover in great detail in this article.
While this article uses the App Store Connect API directly, you might want to consider a tool like Fastlane, specifically the <code>deliver<code> action, which abstracts most of the complexity of the API away and provides a more user-friendly interface, or services with built-in App Store Connect API integrations such as Runway (hey, that's us!).
The process
The App Store Connect API has a comprehensive guide that outlines the process of uploading assets and all the steps that developers need to follow. The process can be summarized in 3 key steps:
- Making an asset reservation: Before uploading any data, you must first tell the App Store Connect API what kind of asset you will be uploading and how big it is. If successful, the response to this request will contain the different requests you must make to upload the asset as well as the ID and information about the entity for which you are uploading an asset.â
- Uploading the asset: After a successful reservation, you will have all the requested information needed to upload the asset. As part of the reservation, the App Store Connect API will split the asset into one or more parts and provide you with the URL, headers, offset and size required for each of them. You can at this point split the asset into all its different parts and upload them in parallel.â
- Committing the reservation: If (and only if) all parts of the asset have been successfully uploaded, you can then make a request to the App Store Connect API telling it that the asset is complete. In this step, you also need to send the checksum of the full asset to the API.
As you can see in the steps above, the process is complex and involves file handling, data manipulation, cryptography and concurrent network requests, which can complicate things significantly. Over the next few sections, you will learn how to implement each of these steps in a familiar language for mobile developers: Swift.
Uploading a screenshot to App Store Connect
For the rest of the article, we will show how the process works by uploading a single screenshot for a specific version's localization using the App Store Connect API and writing a function for each of the steps mentioned previously.
The first thing you need to do to interact with the App Store Connect API is to create an API key and use it to generate a JWT token that you will use to authenticate all your requests. As we mentioned in our Hitchhiker's guide to the App Store Connect API, you should leverage the power of existing libraries that handle the authentication process for you and give you type-safe access to the API's endpoints.
For this article, we will use the appstoreconnect-swift-sdk, a Swift package that provides a type-safe way to interact with the App Store Connect API. Setting up the SDK is as straightforward as initializing an <code>APIConfiguration<code> object with either a team or individual API key and then using it to create an <code>APIClient<code> object that you can use to make requests to the API:
Screenshots need to always be part of a set that describes the device type and provides dimension constraints. For this reason, we will need to pass the <code>ScreenshotSet<code> object that we want to upload the screenshot to, as well as the URL of the file we want to upload.
Making an asset reservation
The first step in the process is to make a reservation for the asset you want to upload by making a <code>POST<code> request to the endpoint. The endpoint will then create a screenshot entity and return information about the new entity such as the id as well as all the information needed to upload the asset.
In the body of the <code>POST<code> request, we must send the file name and its size and tell the API which screenshot set we are uploading the asset to:
A lot is going on in the function above, so let's break it down:
- We create a <code>POST<code> request to the <code>appScreenshots<code> endpoint with the file name and size in the body of the request through the body's attributes field, which we pass as parameters to the function. We also specify the screenshot set we want to upload the asset to by using the body's relationships field.
- We make the request to the API and get the response back.
- We parse the response and extract the upload operations to map them into an array of <code>URLRequest<code> objects that we will use to upload the asset.
- We get an image data chunk based on the offset and length provided by the API.
- We create a <code>URLRequest<code> object for each upload operation and set the method, headers and body of the request based on the information provided by the API.
- We return the reservation ID and the array of requests that we will use to upload the asset.
Now that we have the method to reserve the asset, let's add it to the <code>uploadScreenshot<code> function we created earlier:
Uploading the asset
Now that we have the screenshot ID and the list of <code>URLRequests<code> we need to call, we can start uploading the asset. The most efficient way to do this is to upload all the parts in parallel using structure concurrency and wait for all the requests to finish before moving on to the next step:
As you can see, the method above uses a <code>TaskGroup<code> to parallelize the network requests for all different parts of the asset. This request does not need to be authenticated. As we did before, let's add this method to the <code>uploadScreenshot<code> function:
Committing the reservation
Last but not least, we need to tell the API that we have successfully uploaded all parts of the asset and that it can now update the status of the entity to <code>UPLOAD_COMPLETE<code>. To do this, we need to make a <code>PATCH<code> request to the endpoint.
The request body should contain the <code>md5<code> checksum of the full asset and a flag that tells the API that the asset has been uploaded:
Let's finally add this method to the <code>uploadScreenshot<code> function:
And that's it! That's the full process of uploading a screenshot to App Store Connect using the App Store Connect API. You can now use the <code>uploadScreenshot<code> function to upload screenshots for all your localizations and device types in a fully automated way, and using a language you are familiar with!