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

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, 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, 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, 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), 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:

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 Receives uploads, validates encoding, stores files, creates Import models.
app/Livewire/Importer.php Livewire component powering the wizard UI, field mapping, and progress feedback.
app/Importer/Importer.php Abstract base class containing CSV parsing, transaction handling, and rowIsBlank() logic.
app/Importer/AssetImporter.php Concrete implementation extending Importer for asset-specific validation.
app/Models/Import.php Eloquent model representing uploaded import files and metadata.
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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →