Import assets to Media Library
Import assets in bulk and automatically categorize with aspect data.
When importing assets to Media Library, there are two primary goals:
- Upload the media so it can be used in a studio or another application.
- Assign aspect data so that the asset is categorized and tagged correctly.
There are multiple ways to import assets into your library to accomplish these goals together. The recommended way is to use the Sanity CLI. You can run npx sanity@latest media import --help for a quick summary of syntax and options.
Import using the CLI
The media import command operates on a directory or archive that can have three components:
- An
imagesdirectory for files that should be uploaded as an image. - A
filesdirectory for non-image files. - A
data.ndjsonfile that contains aspect data for any of the files contained in theimagesorfilesdirectories.
product-photos
├── data.ndjson
├── images
│ └── ...all image files
└── files
└── ...all other filesThe import command uploads every file directly inside the images and files directories. Files in subdirectories of those directories are not imported — flatten them first.
data.ndjson is required. The import fails with No data.ndjson file found in import source <path> if it is missing. The images and files directories are individually optional, but at least one of them must contain a file — otherwise the import fails with No assets to import.
data.ndjson format
data.ndjson is a newline-delimited JSON file (NDJSON) that can contain aspect information for any of the processed files. Each line must be a valid JSON object containing the information that should be associated with a single file.
These example JSON objects each define a few aspects for a file:
{
"filename": "images/hero-shot.jpg",
"aspects": {
"description":"A dog chasing a stick"
}
}{
"filename": "images/studio-portrait.jpg",
"aspects": {
"licensedPhotograph": {
"expiration": "2026-05-02T17:34:00.000Z",
"photographer": {
"_ref": "dataset:YOUR_PROJECT_ID.example:photographer-7926527",
"_type": "globalDocumentReference",
"_weak": true
}
}
}
}However, NDJSON uses the newline character as a delimiter to combine multiple JSON objects into a single file. Here are the two example objects combined into a single NDJSON file:
{"filename": "images/hero-shot.jpg","aspects":{"description":"A dog chasing a stick"}}
{"filename": "images/studio-portrait.jpg","aspects":{"licensedPhotograph":{"expiration": "2026-05-02T17:34:00.000Z","photographer": {"_ref":"dataset:YOUR_PROJECT_ID.example:photographer-7926527","_type":"globalDocumentReference","_weak": true}}}}Each JSON object for an asset has two components:
filename: The relative path to the file you want to apply the aspect information to.aspects: The aspect data that should be saved attached to the asset.
After you've prepared your files, run the import with the Sanity CLI:
What should I import?
In some cases you want to import your directory, such as when you've exported your library, made changes to the ndjson file, and are importing it back into the same library.
In other cases you want to compress your assets into a tarball / tar file (.tar, .tar.gz, or .tgz), which includes the ndjson file and your assets.
npx sanity@latest media import product-photos # or npx sanity@latest media import product-photos.tar.gz
pnpm dlx sanity@latest media import product-photos # or pnpm dlx sanity@latest media import product-photos.tar.gz
yarn dlx sanity@latest media import product-photos # or yarn dlx sanity@latest media import product-photos.tar.gz
bunx sanity@latest media import product-photos # or bunx sanity@latest media import product-photos.tar.gz
Pro tip
If a file matches an existing asset in the library, that asset is not uploaded a second time, and its aspect data in data.ndjson is not applied. To set aspect data on assets that are already in the library — including assets that have no aspect data yet — run the import with --replace-aspects. That option replaces all versions of the aspect data, published and draft.
Import using a client library
If you prefer not to use the Sanity CLI import tool, you can run the import yourself with the HTTP API:
There are some common pitfalls to keep in mind:
- Concurrency: While you may have thousands of assets to import, don't trigger thousands of requests in parallel. Parallel requests exceed API rate limits and can fail. Use a queue with a low concurrency to keep your import below the API rate limit.
- API usage limits: Importing large libraries can quickly cause a lot of requests, especially if you import a single asset per request. Send multiple mutations within a single transaction.
- Mutation size limits: While it's a good idea to do multiple mutations per transaction, make sure the size of the request is within our limits, in terms of byte size.