How to Add Custom Fields in Snipe-IT: Complete Admin Guide

Adding custom fields in Snipe-IT requires navigating to Admin → Custom Fields → Add New, which triggers a dynamic schema update that adds a new column to the assets table to store the field values.

Snipe-IT is an open-source IT asset management application that allows administrators to extend data models beyond default attributes. When you add custom fields in Snipe-IT, the system creates structured metadata columns directly in the database, enabling robust querying and validation while maintaining referential integrity.

Understanding the Three-Layer Architecture

Snipe-IT implements custom fields through a tightly-coupled stack spanning the UI, controller logic, and database schema. This architecture ensures that field definitions and storage remain synchronized automatically.

Creating Custom Fields via the Admin Interface

To add a custom field through the web interface, navigate to Admin → Custom Fields → Add New. The Livewire component CustomFieldEditor loads the view resources/views/livewire/custom-field-editor.blade.php, presenting a form for field configuration.

Key configuration options include:

  • Name: The display label (slugified into the database column name)
  • Element: Input type (text, date picker, checkbox, etc.)
  • Format: Data type constraints (DATE, DATETIME, or default TEXT)
  • Encryption: Whether values should be stored encrypted

The component validates input using CustomField::getRules() and format-specific constraints like allowedElementKeysForFormat before persistence.

How Snipe-IT Manages Database Schema Changes

The core mechanism for adding custom fields in Snipe-IT resides in the model's boot() method. When CustomField::create() executes, the created event fires code that dynamically alters the assets table:

// From app/Models/CustomField.php
Schema::table(self::$table_name, function ($table) use ($custom_field) {
    $column = $custom_field->convertUnicodeDbSlug();
    if ($custom_field->format === 'DATETIME') {
        $table->dateTime($column)->nullable();
    } elseif ($custom_field->format === 'DATE') {
        $table->date($column)->nullable();
    } else {
        $table->text($column)->nullable();
    }
});

Critical implementation details:

  • self::$table_name references the assets table where values are physically stored
  • Column names follow the pattern _snipeit_{slug}_{id} via convertUnicodeDbSlug()
  • DATE and DATETIME formats create native date columns; all others use TEXT
  • After schema modification, the model updates its db_column attribute to track the physical column name

Adding Custom Fields Programmatically

Via API

The REST API endpoint handles authorization through $this->authorize('create', CustomField::class) and delegates validation to the model:

// app/Http/Controllers/Api/CustomFieldsController.php
$field = new CustomField;
$field->fill($request->all());
$field->save();

Via Database Seeders

For automated deployments, instantiate the model directly in seeders:

use App\Models\CustomField;

CustomField::create([
    'name' => 'Warranty Expiration',
    'element' => 'date_picker',
    'format' => 'DATE',
    'field_encrypted' => false,
    'show_in_listview' => true,
]);

Running this code automatically executes the schema changes, adding a column like _snipeit_warranty_expiration_1 to the assets table.

Accessing Values in PHP

Once added, custom field values are accessible as array properties on asset models:

$asset = Asset::find($id);
$customFields = $asset->custom_fields;
echo $customFields['_snipeit_warranty_expiration_1']; // "2025-12-31"

The CustomFieldsTransformer handles serialization for API responses, while resources/views/partials/bootstrap-table.blade.php manages format-specific rendering (converting URLs to links, booleans to icons, etc.).

Updating and Deleting Custom Fields

Modifying existing fields triggers additional schema operations managed in the updating hook:

  • Renaming: Changing the field name executes Schema::table(... renameColumn ...) to preserve existing data while updating the column identifier.
  • Format Changes: Snipe-IT blocks format changes from DATE or DATETIME to other types to prevent data loss.
  • Deletion: Removing a field via the UI or API executes dropColumn on the assets table.

All schema operations are encapsulated in app/Models/CustomField.php methods, ensuring that structural changes remain synchronized with the field definitions.

Summary

  • Snipe-IT stores custom field values in dynamically created columns on the assets table, prefixed with _snipeit_ and suffixed with the field ID.
  • The CustomField model's boot() method handles automatic schema creation, renaming, and deletion via Laravel's Schema builder.
  • DATE and DATETIME formats create native date columns, while other formats use TEXT columns.
  • Livewire components provide real-time validation and UI updates, while API and web controllers share the same underlying model logic.
  • Format conversions that would destroy data (e.g., date to text) are explicitly blocked in the model's updating logic.

Frequently Asked Questions

How do I add a custom field to assets in Snipe-IT?

Navigate to Admin → Custom Fields → Add New, specify the field name, element type, and format, then save. The system automatically creates a corresponding column in the assets table using the slugified name with a _snipeit_ prefix.

Can I rename a custom field without losing data?

Yes. When you update the field name in the UI or via API, the updating hook in app/Models/CustomField.php triggers renameColumn on the database, preserving all existing values while updating the column identifier.

Why can't I change a custom field from Date to Text format?

Snipe-IT blocks format changes from DATE or DATETIME to other types in the model's updating method to prevent data loss. You must delete the field and create a new one if you need a different format, though this will result in data loss.

Where does Snipe-IT store custom field values?

Values are stored directly in the assets table in dynamically generated columns (e.g., _snipeit_field_name_5), not in a separate EAV table. This design enables efficient querying and indexing while the CustomField model maintains the mapping between logical field names and physical column names.

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 →