Update your app to use the new files model
In early 2024, Shopify introduced a new way to handle files. Instead of creating duplicate file objects for each product, theme, or other resource, the new system uses a single file that can be referenced across a shop. This makes file management more efficient and consistent across a store, reducing the number of duplicates and simplifying the process of updating files.
For example, if you have a product image used across multiple themes, product pages, and marketing materials, you only need to upload and manage one instance of that file. If you need to update the image, you only need to replace it once, and the change will automatically reflect everywhere the file is used.
This change affects how you create and manage files in your app. The following sections provide examples of how to update your app to use the new model.
Anchor to ProductsProducts
Previously, apps would create a Product Image
for each product using the REST Admin API. With the new files model, apps should use the fileCreate
and fileUpdate
mutations to create or update file. The fileUpdate
mutation can be used to either updated the contents of a file, or associate it to a product. When working directly with products, apps should use the productCreate
, productUpdate
, or productSet
mutations to associate files with corresponding products.
This change reflects our move towards a more streamlined approach where file information and associations are managed through the File APIs rather than through product-specific endpoints.
For example, if an app wanted to add an image to a product, it would previously use the following REST API call:
PUT /admin/api/2024-07/products/{product_id}/images.json
JSON
Now, the same operation can be achieved asynchronously using the following GraphQL Admin API calls:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
You can then poll the file fileStatus using this query until it's ready:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL query
The status
field will be one of: UPLOADED
, PROCESSING
, READY
, or FAILED
. Once the status is READY
, you can proceed with using the file.
Next, you can associate the file with the product using the productSet
mutation:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
Anchor to Alternative approach using ,[object Object]Alternative approach using fileUpdate
fileUpdate
You can also update an existing file's references using the fileUpdate
mutation:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
The fileType
parameter in the file GID is the type of file object that you are updating. This is either MediaImage
, Video
, GenericFile
, ExternalVideo
, or Model3d
.
Anchor to REST API changes to support migrationREST API changes to support migration
As of version 2025-01
, the REST Admin API for the product image resource will return a files image GID instead of a product image GID.
This change helps simplify migration from REST to GraphQL when working with product images created before the unified files ID system.
Anchor to GID Format ChangesGID Format Changes
Version | GID Format | Example |
---|---|---|
Previous | ProductImage GID | "gid://shopify/ProductImage/43701248884792" |
New (2025-01 ) | mediaImage GID | "gid://shopify/MediaImage/12379812379123" |
Anchor to Key BenefitsKey Benefits
- Direct use of returned files image GID in GraphQL queries and mutations
- No ID translation or lookup needed
- Ability to re-ruse existing files across different products
Anchor to Version CompatibilityVersion Compatibility
- Only affects the
2025-01
API version and newer - Older versions will continue returning ProductImage GID
Anchor to Deprecated APIs and their recommended replacementsDeprecated APIs and their recommended replacements
The following product-centric files APIs are being retired:
Deprecated (2024-10) | Replacement |
---|---|
productAppendImages | fileCreate then productCreate or productSet |
productDeleteImages | fileDelete |
productImageUpdate | fileUpdate |
Anchor to Upcoming API ChangesUpcoming API Changes
We are transitioning from product-centric files APIs to file-centric APIs. Here's how the current APIs will map to the new system:
Current Product-Centric API | Future File-Centric API |
---|---|
productCreateMedia | fileCreate then productCreate or productSet |
productDeleteMedia | fileDelete |
Anchor to CollectionsCollections
When working with collections, the process is slightly different from products. Because collections are not yet fully migrated to use files references, you need to pass files to collection mutations directly.
Anchor to Creating Collections with filesCreating Collections with files
To add files to a new collection, follow these steps:
Note: If you're using an external image URL and don't need to store the file in Shopify's CDN, you can skip directly to step 3 and use your external URL in the src
field.
- Create or obtain the file's GID using
fileCreate
:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
- Query the file to get the CDN URL:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL query
- Create the collection using the image URL:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
Anchor to Updating Collections with filesUpdating Collections with files
The process for updating a collection's files follows the same steps:
- Create or obtain the mediaImage GID using
fileCreate
or querying thefile
object - Query the
file
to get its corresponding CDN URL - Update the collection using the image URL:
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
Anchor to Asynchronous file processingAsynchronous file processing
A key change to the files system is the shift from immediate to asynchronous processing. Updates now take effect after the mutation completes, improving efficiency and reducing the risk of concurrent update conflicts.
It's important to optimize your approach to avoid unnecessary polling when working with multiple images. Rather than polling each file individually, use a single GraphQL query to check the status of all files at once.