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

> Learn how to add custom fields in Snipe-IT with our complete admin guide. Effortlessly track unique asset information and enhance your inventory management.

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

---

**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.

- **UI Layer**: The [`app/Livewire/CustomFieldEditor.php`](https://github.com/grokability/snipe-it/blob/main/app/Livewire/CustomFieldEditor.php) component renders dynamic forms and handles real-time validation.
- **Controller Layer**: [`CustomFieldsController.php`](https://github.com/grokability/snipe-it/blob/main/CustomFieldsController.php) (web) and [`Api/CustomFieldsController.php`](https://github.com/grokability/snipe-it/blob/main/Api/CustomFieldsController.php) (API) authorize requests and delegate persistence.
- **Model Layer**: The `CustomField` model in [`app/Models/CustomField.php`](https://github.com/grokability/snipe-it/blob/main/app/Models/CustomField.php) manages the physical database schema, automatically adding columns to the `assets` table when fields are created.

## 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`](https://github.com/grokability/snipe-it/blob/main/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:

```php
// 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:

```php
// 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:

```php
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:

```php
$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`](https://github.com/grokability/snipe-it/blob/main/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`](https://github.com/grokability/snipe-it/blob/main/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`](https://github.com/grokability/snipe-it/blob/main/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.