# How to Import Assets into Snipe-IT: Complete CSV Guide

> Easily import assets into Snipe-IT with our complete CSV guide. Learn how to bulk-create and update assets efficiently using the built-in importer wizard.

- Repository: [Grokability, Inc./snipe-it](https://github.com/grokability/snipe-it)
- Tags: how-to-guide
- Published: 2026-07-31

---

**Snipe-IT provides a built-in CSV importer that lets you bulk-create or update assets via a three-step wizard or programmatically using the abstract `Importer` class and concrete `AssetImporter`.**

Snipe-IT is the open-source IT asset management system maintained by grokability. Whether you are migrating from a spreadsheet or conducting regular bulk updates, understanding how to import assets into Snipe-IT requires familiarity with its three-tier import architecture that handles everything from file validation to database transactions.

## Snipe-IT Import Architecture Overview

The import workflow is orchestrated by three core components working in sequence:

- **`ImportController`** – Located at [`app/Http/Controllers/Api/ImportController.php`](https://github.com/grokability/snipe-it/blob/main/app/Http/Controllers/Api/ImportController.php), this handles the HTTP request for CSV upload, validates MIME types and encoding, stores the file, and creates an `Import` record.
- **`Importer` (Livewire component)** – Found in [`app/Livewire/Importer.php`](https://github.com/grokability/snipe-it/blob/main/app/Livewire/Importer.php), this powers the UI wizard that guides users through selecting the import type, mapping columns, previewing rows, and triggering processing.
- **`Importer` (abstract class)** – Defined in [`app/Importer/Importer.php`](https://github.com/grokability/snipe-it/blob/main/app/Importer/Importer.php), this implements the low-level CSV parsing using `League\Csv\Reader`, row-by-row handling, transaction logic, and database insertion.

## Step-by-Step Import Workflow

### 1. Upload CSV Files

The process begins when the user submits a CSV via the UI ([`resources/views/livewire/importer.blade.php`](https://github.com/grokability/snipe-it/blob/main/resources/views/livewire/importer.blade.php)), which posts to `ImportController::store()`. The controller validates the MIME type, optionally re-encodes non-UTF-8 files, and stores the upload under `storage/app/private/uploads/imports`. It then creates a record in the `imports` table using `App\Models\Import` to track metadata such as the original filename and file size.

### 2. Select Import Type

After upload, the Livewire component reads the stored `Import` record and presents a wizard interface. The user selects the target entity via the `$typeOfImport` property. For asset imports, you choose **Asset**, which instantiates the concrete `AssetImporter` class (extending the abstract `Importer`) to handle the specific validation rules for asset models.

### 3. Map CSV Columns to Model Fields

Column mapping relies on `Importer::$defaultFieldMap`, an array that maps every possible CSV heading to its canonical model attribute (e.g., `asset_tag`, `serial`, `model`). The UI constructs dropdowns for required fields using the `$required_field_model_map` array, which links the target model’s validation rules to the mapping interface. This ensures that mandatory fields like `asset_tag` cannot be left unmapped.

### 4. Preview Before Processing

Before committing changes, the importer displays the first **N** rows defined by `Importer::PREVIEW_ROW_LIMIT`. This preview step lets you verify that the column mapping correctly interprets your data, catching issues like misaligned headers or encoding errors before database insertion begins.

### 5. Process the Import

When you click **Process**, the Livewire component delegates to the concrete importer (e.g., `AssetImporter`). The import runs inside a database transaction (`DB::transaction`) to ensure atomicity. The abstract class iterates through CSV rows, skipping blank rows using the `rowIsBlank()` method, and creates or updates records based on the `$updating` flag. Progress streams back to the UI via the `$progress` and `$message` properties.

## Configuration Options

The importer respects several settings that modify behavior:

- **Full Multiple Company Support** – When the `full_multiple_companies_support` setting is enabled, the import can filter by or assign a `company_id` column to ensure assets land in the correct company scope.
- **Backup Option** – The wizard can request a pre-import backup; the controller’s `process()` method toggles `$backupRequested` to trigger a database dump before processing begins.
- **Custom Fields** – Custom fields are cached in the `$customFields` property and populated automatically when the CSV contains matching headings, allowing dynamic attribute assignment without manual schema updates.

## Programmatic Asset Import

You can run asset imports outside the UI—useful for scheduled jobs or custom Artisan commands. The following example demonstrates loading a CSV and running the import directly:

```php
use App\Importer\Importer;
use League\Csv\Reader;

// 1️⃣ Load CSV (string or file path)
$csvPath = storage_path('app/private/uploads/imports/my_assets.csv');
$csv = Reader::createFromPath($csvPath, 'r');

// 2️⃣ Instantiate the concrete importer (AssetImporter extends Importer)
//    The concrete class lives in `app/Importer/AssetImporter.php`
$importer = new \App\Importer\AssetImporter($csvPath);

// 3️⃣ Optional: customize field mapping if your headings differ
$importer->fieldMap = [
    'asset_tag' => 'Tag',
    'serial'    => 'Serial Number',
    'model'     => 'Model Name',
    // …other mappings…
];

// 4️⃣ Run the import
$importer->import(); // processes the whole file inside a transaction

```

## Key Source Files Reference

| File | Purpose |
|------|---------|
| [`app/Http/Controllers/Api/ImportController.php`](https://github.com/grokability/snipe-it/blob/main/app/Http/Controllers/Api/ImportController.php) | Receives uploads, validates encoding, stores files, creates `Import` models. |
| [`app/Livewire/Importer.php`](https://github.com/grokability/snipe-it/blob/main/app/Livewire/Importer.php) | Livewire component powering the wizard UI, field mapping, and progress feedback. |
| [`app/Importer/Importer.php`](https://github.com/grokability/snipe-it/blob/main/app/Importer/Importer.php) | Abstract base class containing CSV parsing, transaction handling, and `rowIsBlank()` logic. |
| [`app/Importer/AssetImporter.php`](https://github.com/grokability/snipe-it/blob/main/app/Importer/AssetImporter.php) | Concrete implementation extending `Importer` for asset-specific validation. |
| [`app/Models/Import.php`](https://github.com/grokability/snipe-it/blob/main/app/Models/Import.php) | Eloquent model representing uploaded import files and metadata. |
| [`config/importer.php`](https://github.com/grokability/snipe-it/blob/main/config/importer.php) | Configuration defaults for import behavior, chunk sizes, and backup options. |

## Summary

- Snipe-IT imports assets via a robust CSV pipeline using `ImportController` for uploads, Livewire `Importer` for the UI, and an abstract `Importer` class for database logic.
- The workflow requires uploading a CSV, selecting the Asset type, mapping columns using `$defaultFieldMap`, previewing rows, and processing within a database transaction.
- Configuration options include multi-company support, pre-import backups, and automatic custom field mapping.
- Programmatic imports use `AssetImporter` extending the abstract `Importer`, supporting custom field maps and running inside `DB::transaction`.

## Frequently Asked Questions

### What file format does Snipe-IT require for asset imports?

Snipe-IT requires CSV files. The `ImportController` validates MIME types and automatically re-encodes files to UTF-8 if necessary. Store your data with standard comma separators and ensure your first row contains headers that map to Snipe-IT fields like `asset_tag` and `serial`.

### Can I update existing assets via CSV import instead of creating new ones?

Yes. The abstract `Importer` class supports an `$updating` flag. When enabled, the importer identifies existing records (typically by `asset_tag` or another unique key) and updates their attributes rather than creating new database rows. This is handled inside the `DB::transaction` block to ensure data integrity.

### Where are uploaded import files stored in Snipe-IT?

Uploaded CSVs are stored in `storage/app/private/uploads/imports` according to the `ImportController::store()` method. The `App\Models\Import` Eloquent model tracks the file path, original name, and upload metadata in the `imports` database table, allowing the Livewire component to retrieve the file during the mapping and preview phases.

### How do I handle custom fields when importing assets?

Custom fields are cached in the `$customFields` property during initialization. If your CSV contains column headings that match the names of custom fields defined in your Snipe-IT instance, the importer automatically maps those values to the corresponding custom field entries without requiring manual schema configuration.