Contents

Uploading and managing image assets

Reserve, upload, and commit an image to your app’s asset library, then update, archive, or delete it.

Overview

An asset library image is a reusable image you upload once and place across your App Store surfaces. Uploading one follows the same reserve-upload-commit pattern as other App Store Connect assets: you create a reservation that returns upload operations, transfer the bytes to those URLs, then commit the reservation so App Store Connect can process the file. This article walks through that workflow and the management operations that follow.

For the shared four-step asset delivery model, see Uploading Assets to App Store Connect. For the broader asset library concept, see Understanding the App Asset Library.

Confirm specifications before you begin

Find your app’s asset library and confirm the image specifications:

  • Read the library with GET /v1/apps/{id}/assetLibrary (Read related asset library) and note the returned appAssetLibraries id. You relate every image you upload to this library.

  • Query the reference data with GET /v1/appAssetLibraryRefData (List app asset library ref data) to read the valid imageSpecs (dimensions, aspect ratios, allowed file extensions, and maximum file sizes) for the placement types you’re targeting. For more information about specifications, see Discovering asset specifications.

Image specifications state exact dimensions, not ranges. Resize your file to match a specification before you reserve it; App Store Connect matches the file you upload against the catalog during processing.

Reserve the image

Create the image with POST /v1/appAssetLibraryImages (Create an app asset library image). Supply the filename, the file size in bytes, and a category (AppAssetLibraryAssetCategory), and relate the image to your asset library. The referenceName attribute is optional and helps you identify the asset later.

{
  "data": {
    "type": "appAssetLibraryImages",
    "attributes": {
      "fileName": "ync-menu-6-9.png",
      "fileSize": 14619,
      "category": "APP_SCREENSHOTS_AND_PREVIEWS",
      "referenceName": "Menu screen — iPhone 6.9\""
    },
    "relationships": {
      "assetLibrary": {
        "data": {
          "type": "appAssetLibraries",
          "id": "1234567890"
        }
      }
    }
  }
}

A successful response returns the image id, a state of AWAITING_UPLOAD, and an uploadOperations array. Each operation specifies the HTTP method, url, length, offset, and requestHeaders to use when you transfer the bytes:

{
  "data": {
    "type": "appAssetLibraryImages",
    "id": "f4000005-e036-8f0b-8018-d259974bee61",
    "attributes": {
      "category": "APP_SCREENSHOTS_AND_PREVIEWS",
      "createdDate": "2026-08-11T22:44:12.019637Z",
      "lastModifiedDate": "2026-08-11T22:44:12.019637Z",
      "fileName": "ync-menu-6-9.png",
      "fileSize": 14619,
      "imageAsset": null,
      "referenceName": "Menu screen — iPhone 6.9\"",
      "specId": null,
      "state": "AWAITING_UPLOAD",
      "stateDetails": null,
      "uploadOperations": [
        {
          "method": "PUT",
          "url": "https://store-030.blobstore.apple.com/...",
          "length": 14619,
          "offset": 0,
          "requestHeaders": [
            { "name": "Content-Type", "value": "image/png" }
          ]
        }
      ]
    }
  }
}

Note the id; you use it to upload, commit, and later manage the image. imageAsset and specId are null at this stage; App Store Connect fills both in after processing.

Upload the image

Transfer the file to the URLs from uploadOperations. For each operation, make an HTTP request using the specified method, url, and requestHeaders, and send the bytes from the given offset and length in the request body. Large files return multiple operations; upload the parts concurrently and in any order to improve performance. The upload URLs are unauthenticated and time-limited, so you don’t send a JSON Web Token (JWT), and you don’t share them.

The image stays in AWAITING_UPLOAD while you transfer the parts.

Commit the upload

After every part uploads, commit the reservation with PATCH /v1/appAssetLibraryImages/{id} (Modify an app asset library image) by setting uploaded to true:

{
  "data": {
    "type": "appAssetLibraryImages",
    "id": "f4000005-e036-8f0b-8018-d259974bee61",
    "attributes": {
      "uploaded": true
    }
  }
}

The image moves to UPLOAD_COMPLETE, and processing begins.

Verify processing

Processing is asynchronous. Re-fetch the image with GET /v1/appAssetLibraryImages/{id} (Read an app asset library image) to check its state:

  • UPLOAD_COMPLETE: App Store Connect received the file and is processing it.

  • PREPARE_FOR_SUBMISSION: Processing succeeded and the image is ready to place.

  • FAILED: Processing didn’t succeed. Read stateDetails for the reason, then delete the image and start over with a new reservation.

When processing succeeds, three attributes become readable. Here’s the example response, truncated for clarity:

{
  "fileName": "ync-menu-6-9.png",
  "state": "PREPARE_FOR_SUBMISSION",
  "specId": "f56c777c-99ea-5760-97ae-27c5f8cbb884",
  "imageAsset": {
    "templateUrl": "https://is1.mzstatic.com/image/thumb/AOsFKpK1JfF_vrxSCSbIew/{w}x{h}bb.{f}",
    "width": 1290,
    "height": 2796
  }
}

specId is the specification to which App Store Connect matched your file, in this case the 1290×2796 iPhone screenshot specification. You never send specId yourself. Compare the returned value against the reference data to confirm your file landed on the specification you intended, because a file that matches a different specification limits which placement groups accept it.

Read imageAsset for the processed image: substitute width, height, and format into templateUrl to render a thumbnail.

Update an image

Use PATCH /v1/appAssetLibraryImages/{id} (Modify an app asset library image) to change an image’s referenceName. The image binary is immutable after commit; to change the picture, upload a new asset and replace the placements that use it.

{
  "data": {
    "type": "appAssetLibraryImages",
    "id": "f4000005-e036-8f0b-8018-d259974bee61",
    "attributes": {
      "referenceName": "Menu screen (Fall 2026)"
    }
  }
}

Archive an image

To retire an image without removing its record, set archived to true with the same PATCH endpoint. Archiving moves the image to ARCHIVED and hides it from active use.

Archiving works only on an approved asset. Archiving one that’s still in PREPARE_FOR_SUBMISSION returns a 409:

{
  "errors": [
    {
      "status": "409",
      "code": "STATE_ERROR.INVALID_ASSET_STATE",
      "title": "The request cannot be fulfilled because of the state of another resource.",
      "detail": "Only an approved asset can be archived."
    }
  ]
}

Delete an image

To remove an image entirely, use DELETE /v1/appAssetLibraryImages/{id} (Delete an app asset library image), which returns 204 No Content on success.

Find image placements

To see the placements that reuse an image, use GET /v1/appAssetLibraryImages/{id}/placements (List related placements), or fetch just the relationship linkages with GET /v1/appAssetLibraryImages/{id}/relationships/placements (List the placement IDs for an app asset library image).

This is also the check to run before a delete. Filter by surface, for example, filter[appStoreVersionLocalization], or by filter[placementType] and filter[placementGroup] to narrow the results.

List the images in your library

Read the whole library with GET /v1/appAssetLibraries/{id}/images (List related images). Useful filters and sorts:

  • filter[state]: Find assets stuck in AWAITING_UPLOAD, or list only APPROVED ones.

  • filter[category], filter[specId], filter[referenceName], filter[id].

  • sort by createdDate, lastModifiedDate, or referenceName. Prefix with - to reverse.

Filtering on filter[state]=AWAITING_UPLOAD is a practical way to find abandoned reservations and clean them up.

After your image reaches PREPARE_FOR_SUBMISSION, place it on a surface. For more information, see Placing assets on your App Store surfaces.

See Also

Essentials