# @sanity/import

> Import documents to a Sanity dataset

Latest version **7.0.4** (published 2026-09-18) · MIT license · 0 weekly downloads

## Install

```sh
npm install @sanity/import
pnpm add @sanity/import
yarn add @sanity/import
bun add @sanity/import
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 7.0.4 |
| Published | 2026-09-18 |
| First published | 2017-09-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=22.12.0 |
| Dependencies | 7 |
| Unpacked size | 247.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| Author | Sanity.io <hello@sanity.io> |
| Maintainers | sanity-svc.npm, sanity-io |
| Keywords | cms, content, headless, import, ndjson, realtime, sanity |

## Links

- npm: https://www.npmjs.com/package/@sanity/import
- Repository: https://github.com/sanity-io/import
- Homepage: https://www.sanity.io/
- Issues: https://github.com/sanity-io/import/issues
- npm.io page: https://npm.io/package/@sanity/import

## Dependencies (7)

- [obug](https://npm.io/package/obug.md) ^3.0.0
- [p-map](https://npm.io/package/p-map.md) ^7.0.6
- [get-it](https://npm.io/package/get-it.md) ^9.5.4
- [modern-tar](https://npm.io/package/modern-tar.md) ^0.8.5
- [@sanity/mutator](https://npm.io/package/@sanity/mutator.md) ^6.14.0
- [@sanity/asset-utils](https://npm.io/package/@sanity/asset-utils.md) ^2.3.0
- [@sanity/generate-help-url](https://npm.io/package/@sanity/generate-help-url.md) ^4.0.0

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 7.0.4 (latest) — 2026-09-18
- 2.36.6 (v2) — 2024-11-07
- 3.37.5-alpha.1 (alpha) — 2024-05-17
- 3.37.2-canary.92 (canary) — 2024-04-11
- 3.37.3-cds-unstable.27 (cds-unstable) — 2024-04-11
- 3.36.5-next.86 (next) — 2024-04-09
- 3.36.5-v3-esm.81 (v3-esm) — 2024-04-08
- 3.29.2-pt-input.68 (pt-input) — 2024-02-15
- 3.28.1-pt-input-focuspath.31 (pt-input-focuspath) — 2024-02-13
- 3.23.5-purple-monkey-dishwasher.35 (purple-monkey-dishwasher) — 2024-01-09
- 3.23.5-edx-980.36 (edx-980) — 2024-01-09
- 3.23.5-comments.29 (comments) — 2024-01-09
- 3.23.5-facelift.24 (facelift) — 2024-01-06
- 3.22.3 (stable) — 2023-12-21
- 3.23.2-EDX937.1 (EDX937) — 2023-12-21
- … 1180 more at https://npm.io/package/@sanity/import/versions

## README

# @sanity/import

Imports documents from an [ndjson](https://github.com/ndjson/ndjson-spec)-stream to a Sanity dataset

## Requirements

- Node.js >= 22.12.0

## Installing

```
npm install --save @sanity/import
```

## Usage

```js
import fs from 'node:fs'
import {createClient} from '@sanity/client'
import {sanityImport} from '@sanity/import'

const client = createClient({
  projectId: '<your project id>',
  dataset: '<your target dataset>',
  token: '<token-with-write-perms>',
  useCdn: false,
})

// Input can either be a readable stream (for a `.tar.gz` or `.ndjson` file), a folder location (string), or an array of documents
const input = fs.createReadStream('my-documents.ndjson')

const options = {
  /**
   * A Sanity client instance, preconfigured with the project ID and dataset
   * you want to import data to, and with a token that has write access.
   */
  client: client,

  /**
   * Which mutation type to use for creating documents:
   * `create` (default)  - throws error if document IDs already exists
   * `createOrReplace`   - replaces documents with same IDs
   * `createIfNotExists` - skips document with IDs that already exists
   *
   * Optional.
   */
  operation: 'create',

  /**
   * Function called when making progress. Gets called with an object of
   * the following shape:
   * `step` (string) - the current step name of the import process
   * `current` (number) - the current progress of the step, only present on some steps
   * `total` (number) - total items before complete, only present on some steps
   */
  onProgress: (progress) => {
    /* report progress */
  },

  /**
   * Whether or not to allow assets in different datasets. This is usually
   * an error in the export, where asset documents are part of the export.
   *
   * Optional, defaults to `false`.
   */
  allowAssetsInDifferentDataset: false,

  /**
   * Whether or not to allow unicode replacement characters (U+FFFD) in imported
   * documents. This is often a sign of a corrupt export.
   *
   * Optional, defaults to `false`.
   */
  allowReplacementCharacters: false,

  /**
   * Whether or not to allow failing assets due to download/upload errors.
   *
   * Optional, defaults to `false`.
   */
  allowFailingAssets: false,

  /**
   * Whether or not to replace any existing assets with the same hash.
   * Setting this to `true` will regenerate image metadata on the server,
   * but slows down the import.
   *
   * Optional, defaults to `false`.
   */
  replaceAssets: false,

  /**
   * Whether or not to skip cross-dataset references. This may be required
   * when importing a dataset with cross-dataset references to a different
   * project, unless a dataset with the referenced name exists.
   *
   * Optional, defaults to `false`.
   */
  skipCrossDatasetReferences: false,

  /**
   * Whether or not to import system documents (like permissions, custom retention, and content releases).
   * This is usually not necessary, and may cause conflicts if the target dataset
   * already contains these documents. On a new dataset, it is recommended that roles are re-created
   * manually, and that any custom retention policies are re-created manually.
   *
   * Optional, defaults to `false`.
   */
  allowSystemDocuments: false,
}

sanityImport(input, options)
  .then(({numDocs, warnings}) => {
    console.log('Imported %d documents', numDocs)
    // Note: There might be warnings! Check `warnings`
  })
  .catch((err) => {
    console.error('Import failed: %s', err.message)
  })
```

## Future improvements

- When documents are imported, record which IDs are actually touched
  - Only upload assets for documents that are still within that window
  - Only strengthen references for documents that are within that window
  - Only count number of imported documents from within that window
- Asset uploads and strengthening can be done in parallel, but we need a way to cancel the operations if one of the operations fail
- Introduce retrying of asset uploads based on hash + indexing delay
- Validate that dataset exists upon start
- Reference verification
  - Create a set of all document IDs in import file
  - Create a set of all document IDs in references
  - Create a set of referenced ID that do not exist locally
  - Batch-wise, check if documents with missing IDs exist remotely
  - When all missing IDs have been cross-checked with the remote API
    (or a max of say 100 items have been found missing), reject with
    useful error message.

## License

MIT-licensed. See LICENSE.

---
_Source: https://npm.io/package/@sanity/import · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
