> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/lopiv2/invenicum/llms.txt
> Use this file to discover all available pages before exploring further.

# Asset Types

> Define and manage asset type templates with custom field definitions

## Overview

Asset types define the structure and custom fields for inventory items. Each asset type belongs to a container and includes field definitions that specify what data can be captured for items of that type. Asset types support image uploads, serialization settings, and collection-specific field mappings.

***

## Create Asset Type

<RequestExample>
  ```http theme={null}
  POST /containers/{containerId}/asset-types
  Content-Type: multipart/form-data
  ```
</RequestExample>

Create a new asset type within a container with custom field definitions.

<ParamField path="containerId" type="integer" required>
  ID of the parent container
</ParamField>

<ParamField body="name" type="string" required>
  Asset type name (e.g., "Electronics", "Books", "Collectibles")
</ParamField>

<ParamField body="isSerialized" type="boolean" default="true">
  Whether items of this type are serialized:

  * `true` - Each item is unique with quantity=1 (default)
  * `false` - Items can have variable quantities
</ParamField>

<ParamField body="fieldDefinitions" type="string" required>
  JSON-encoded array of custom field definition objects

  <Expandable title="field definition structure">
    <ParamField body="id" type="string" required>
      Unique identifier for the field (e.g., "brand", "condition")
    </ParamField>

    <ParamField body="label" type="string" required>
      Display label for the field
    </ParamField>

    <ParamField body="type" type="string" required>
      Field type: `text`, `number`, `date`, `boolean`, `select`, `multiselect`, `textarea`
    </ParamField>

    <ParamField body="required" type="boolean" default="false">
      Whether the field is required
    </ParamField>

    <ParamField body="options" type="array">
      Available options for `select` and `multiselect` types
    </ParamField>

    <ParamField body="dataListId" type="integer">
      ID of a DataList to use for dynamic select options
    </ParamField>
  </Expandable>

  Example:

  ```json theme={null}
  [
    {
      "id": "brand",
      "label": "Brand",
      "type": "text",
      "required": true
    },
    {
      "id": "condition",
      "label": "Condition",
      "type": "select",
      "options": ["New", "Like New", "Good", "Fair", "Poor"]
    }
  ]
  ```
</ParamField>

<ParamField body="files" type="file">
  Optional image file for the asset type icon/thumbnail
</ParamField>

<RequestExample>
  ```bash theme={null}
  curl -X POST "https://api.invenicum.com/containers/5/asset-types" \
    -H "Authorization: Bearer {token}" \
    -F "name=Electronics" \
    -F "isSerialized=true" \
    -F 'fieldDefinitions=[{"id":"brand","label":"Brand","type":"text","required":true},{"id":"model","label":"Model","type":"text"},{"id":"condition","label":"Condition","type":"select","options":["New","Like New","Good","Fair"]}]' \
    -F "files=@electronics-icon.jpg"
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "data": {
      "id": 12,
      "name": "Electronics",
      "isSerialized": true,
      "fieldDefinitions": [
        {
          "id": "brand",
          "label": "Brand",
          "type": "text",
          "required": true
        },
        {
          "id": "model",
          "label": "Model",
          "type": "text",
          "required": false
        },
        {
          "id": "condition",
          "label": "Condition",
          "type": "select",
          "required": false,
          "options": ["New", "Like New", "Good", "Fair"]
        }
      ],
      "images": [
        {
          "id": 78,
          "url": "https://storage.example.com/asset-type-12.jpg",
          "altText": null,
          "order": 0
        }
      ],
      "possessionFieldId": null,
      "desiredFieldId": null
    }
  }
  ```
</ResponseExample>

<ResponseField name="data" type="object">
  <Expandable title="properties">
    <ResponseField name="id" type="integer">
      Unique identifier for the asset type
    </ResponseField>

    <ResponseField name="name" type="string">
      Asset type name
    </ResponseField>

    <ResponseField name="isSerialized" type="boolean">
      Whether items are serialized (quantity=1) or can have variable quantities
    </ResponseField>

    <ResponseField name="fieldDefinitions" type="array">
      Array of custom field definitions

      <Expandable title="field definition">
        <ResponseField name="id" type="string">
          Field identifier
        </ResponseField>

        <ResponseField name="label" type="string">
          Display label
        </ResponseField>

        <ResponseField name="type" type="string">
          Field type
        </ResponseField>

        <ResponseField name="required" type="boolean">
          Whether field is required
        </ResponseField>

        <ResponseField name="options" type="array">
          Available options for select fields
        </ResponseField>

        <ResponseField name="dataListId" type="integer">
          Reference to a DataList for dynamic options
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="images" type="array">
      Array of image objects associated with the asset type

      <Expandable title="image properties">
        <ResponseField name="id" type="integer">
          Image ID
        </ResponseField>

        <ResponseField name="url" type="string">
          Full URL to the image
        </ResponseField>

        <ResponseField name="altText" type="string">
          Alternative text
        </ResponseField>

        <ResponseField name="order" type="integer">
          Display order
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="possessionFieldId" type="string">
      Field ID used to track "possessed" count in collections (nullable)
    </ResponseField>

    <ResponseField name="desiredFieldId" type="string">
      Field ID used to track "desired" count in collections (nullable)
    </ResponseField>
  </Expandable>
</ResponseField>

***

## Get Asset Type

<RequestExample>
  ```http theme={null}
  GET /asset-types/{assetTypeId}
  ```
</RequestExample>

Retrieve a single asset type by ID.

<ParamField path="assetTypeId" type="integer" required>
  ID of the asset type to retrieve
</ParamField>

<ResponseExample>
  ```json theme={null}
  {
    "data": {
      "id": 12,
      "name": "Electronics",
      "isSerialized": true,
      "fieldDefinitions": [
        {
          "id": "brand",
          "label": "Brand",
          "type": "text",
          "required": true
        }
      ],
      "images": [],
      "possessionFieldId": null,
      "desiredFieldId": null
    }
  }
  ```
</ResponseExample>

***

## Update Asset Type

<RequestExample>
  ```http theme={null}
  PATCH /asset-types/{assetTypeId}
  Content-Type: multipart/form-data
  ```
</RequestExample>

Update an existing asset type's name, field definitions, or image.

<ParamField path="assetTypeId" type="integer" required>
  ID of the asset type to update
</ParamField>

<ParamField body="name" type="string" required>
  Updated asset type name
</ParamField>

<ParamField body="fieldDefinitions" type="string" required>
  JSON-encoded array of updated field definitions
</ParamField>

<ParamField body="files" type="file">
  New image file to upload (replaces existing)
</ParamField>

<ParamField body="removeExistingImage" type="boolean" default="false">
  Set to `true` to remove the current image without uploading a new one
</ParamField>

<RequestExample>
  ```bash theme={null}
  curl -X PATCH "https://api.invenicum.com/asset-types/12" \
    -H "Authorization: Bearer {token}" \
    -F "name=Consumer Electronics" \
    -F 'fieldDefinitions=[{"id":"brand","label":"Brand Name","type":"text","required":true}]' \
    -F "removeExistingImage=false"
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "data": {
      "id": 12,
      "name": "Consumer Electronics",
      "isSerialized": true,
      "fieldDefinitions": [
        {
          "id": "brand",
          "label": "Brand Name",
          "type": "text",
          "required": true
        }
      ],
      "images": [
        {
          "id": 78,
          "url": "https://storage.example.com/asset-type-12.jpg",
          "altText": null,
          "order": 0
        }
      ]
    }
  }
  ```
</ResponseExample>

***

## Update Collection Fields

<RequestExample>
  ```http theme={null}
  PATCH /asset-types/{assetTypeId}/collection-fields
  Content-Type: application/json
  ```
</RequestExample>

Update the field mappings used for collection tracking. Collections use specific fields to track how many items are possessed vs. desired.

<ParamField path="assetTypeId" type="integer" required>
  ID of the asset type
</ParamField>

<ParamField body="possessionFieldId" type="string">
  Field ID that tracks "possessed" quantity (set to `null` to clear)
</ParamField>

<ParamField body="desiredFieldId" type="string">
  Field ID that tracks "desired" quantity (set to `null` to clear)
</ParamField>

<RequestExample>
  ```json theme={null}
  {
    "possessionFieldId": "qty_owned",
    "desiredFieldId": "qty_wanted"
  }
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "data": {
      "id": 12,
      "name": "Trading Cards",
      "possessionFieldId": "qty_owned",
      "desiredFieldId": "qty_wanted",
      "fieldDefinitions": [
        {
          "id": "qty_owned",
          "label": "Quantity Owned",
          "type": "number"
        },
        {
          "id": "qty_wanted",
          "label": "Quantity Wanted",
          "type": "number"
        }
      ]
    }
  }
  ```
</ResponseExample>

***

## Delete Asset Type

<RequestExample>
  ```http theme={null}
  DELETE /asset-types/{assetTypeId}
  ```
</RequestExample>

Permanently delete an asset type. This operation:

1. First deletes all inventory items of this type (`DELETE /asset-types/{assetTypeId}/assets`)
2. Then deletes the asset type itself

<Warning>
  This is a destructive operation that cannot be undone. All items associated with this asset type will be permanently deleted.
</Warning>

<ParamField path="assetTypeId" type="integer" required>
  ID of the asset type to delete
</ParamField>

<ResponseExample>
  ```text theme={null}
  204 No Content
  ```
</ResponseExample>

### Error Responses

<ResponseExample>
  ```json theme={null}
  {
    "message": "El tipo de activo no existe o ya fue eliminado."
  }
  ```
</ResponseExample>

Common errors:

* `404 Not Found` - Asset type doesn't exist or was already deleted
* `401 Unauthorized` - Invalid or expired authentication token

***

## Field Definition Types

When creating or updating asset types, the following field types are available:

### Text Fields

```json theme={null}
{
  "id": "description",
  "label": "Description",
  "type": "text",
  "required": false
}
```

Single-line text input.

### Textarea Fields

```json theme={null}
{
  "id": "notes",
  "label": "Notes",
  "type": "textarea",
  "required": false
}
```

Multi-line text input.

### Number Fields

```json theme={null}
{
  "id": "price",
  "label": "Purchase Price",
  "type": "number",
  "required": false
}
```

Numeric input (integer or decimal).

### Date Fields

```json theme={null}
{
  "id": "purchase_date",
  "label": "Purchase Date",
  "type": "date",
  "required": false
}
```

Date picker input.

### Boolean Fields

```json theme={null}
{
  "id": "is_certified",
  "label": "Certified Authentic",
  "type": "boolean",
  "required": false
}
```

Checkbox (true/false).

### Select Fields (Single Choice)

```json theme={null}
{
  "id": "condition",
  "label": "Condition",
  "type": "select",
  "required": true,
  "options": ["Mint", "Near Mint", "Excellent", "Good", "Fair", "Poor"]
}
```

Dropdown with predefined options.

### Multi-Select Fields

```json theme={null}
{
  "id": "tags",
  "label": "Tags",
  "type": "multiselect",
  "required": false,
  "options": ["Vintage", "Rare", "Limited Edition", "Signed"]
}
```

Multiple choice selection.

### Dynamic Select (DataList)

```json theme={null}
{
  "id": "category",
  "label": "Category",
  "type": "select",
  "required": false,
  "dataListId": 5
}
```

Dropdown populated from a DataList (see [Containers](/api/inventory/containers#data-lists)).

***

## Best Practices

### Field ID Naming

Use consistent, descriptive IDs:

* Use lowercase with underscores: `serial_number`, `purchase_date`
* Avoid special characters except underscores
* Keep IDs stable - changing them breaks existing item data

### Serialization Strategy

**Use `isSerialized: true` for:**

* Unique items (electronics, collectibles, art)
* Items with serial numbers or unique identifiers
* Items where each instance is distinct

**Use `isSerialized: false` for:**

* Bulk consumables (screws, cables, office supplies)
* Fungible items where individual instances don't matter
* Items tracked by total quantity rather than individual units

### Collection Fields

For collection management:

1. Create number fields for possession and desire tracking
2. Use the Update Collection Fields endpoint to map them
3. The frontend can then show "5/10" style progress indicators

```json theme={null}
{
  "fieldDefinitions": [
    {"id": "owned", "label": "Owned", "type": "number"},
    {"id": "wanted", "label": "Wanted", "type": "number"}
  ],
  "possessionFieldId": "owned",
  "desiredFieldId": "wanted"
}
```

***

## Error Handling

All endpoints return standard HTTP status codes:

* `200 OK` - Request successful
* `201 Created` - Asset type created successfully
* `204 No Content` - Deletion successful
* `400 Bad Request` - Invalid field definitions or malformed JSON
* `401 Unauthorized` - Authentication required
* `404 Not Found` - Asset type not found
* `500 Internal Server Error` - Server error

Error responses include a message:

```json theme={null}
{
  "message": "Error description"
}
```
