Skip to content
Back to skills

Flexible Assets

ASecurity

Use this skill when working with IT Glue flexible assets - custom asset types for structured documentation. Covers flexible asset types, field definitions, creating and managing instances, cross-linking with other resources, and building custom documentation schemas for MSP needs.

  • 48 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added May 27, 2026
data-aijavascriptgojavaapidatabasedocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add wyre-technology/msp-claude-plugins --skill flexible-assets --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Flexible Assets?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Flexible Assets
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wyre-technology-flexible-assets/badge)](https://www.skillsdirectory.com/skills/wyre-technology-flexible-assets)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "IT Glue Flexible Assets"
description: >
  Use this skill when working with IT Glue flexible assets - custom asset types
  for structured documentation. Covers flexible asset types, field definitions,
  creating and managing instances, cross-linking with other resources, and
  building custom documentation schemas for MSP needs.
when_to_use: "When working with custom asset types for structured documentation in IT Glue flexible assets"
triggers:
  - it glue flexible asset
  - custom asset
  - flexible asset type
  - it glue custom documentation
  - flexible asset field
  - custom documentation
  - structured asset
  - it glue template
---

# IT Glue Flexible Assets Management

## Overview

Flexible Assets in IT Glue provide customizable, structured documentation templates. Unlike free-form documents, flexible assets have defined fields and types, enabling consistent documentation across organizations and powerful filtering/searching capabilities.

## Key Concepts

### Flexible Asset Types

Flexible Asset Types define the schema for a category of documentation:

```
Flexible Asset Type: Network Overview
├── Fields:
│   ├── Primary ISP (Text)
│   ├── Backup ISP (Text)
│   ├── Public IP Addresses (Textarea)
│   ├── Firewall (Tag - Configuration)
│   ├── Network Diagram (Upload)
│   └── DNS Provider (Select)
```

### Field Types

| Type | Description | Use Case |
|------|-------------|----------|
| Text | Single line text | Names, identifiers |
| Textarea | Multi-line text | Descriptions, notes |
| Number | Numeric value | Quantities, counts |
| Date | Date picker | Expiration dates |
| Checkbox | Boolean true/false | Flags, toggles |
| Select | Dropdown selection | Predefined options |
| Tag | Link to IT Glue resource | Configurations, contacts |
| Password | Password field | Embedded credentials |
| Upload | File attachment | Diagrams, documents |
| Percent | Percentage value | Utilization, progress |
| Header | Section header | Visual organization |

### Tag Fields

Tag fields create relationships to other IT Glue resources:

| Tag Type | Links To |
|----------|----------|
| Configuration | Configuration items |
| Contact | Contacts |
| Password | Passwords |
| Document | Documents |
| Flexible Asset | Other flexible assets |
| Location | Locations |

## Field Reference

### Flexible Asset Type Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Type identifier |
| `name` | string | Type name |
| `description` | string | Type description |
| `icon` | string | Display icon |
| `enabled` | boolean | Type enabled status |

### Flexible Asset Fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Asset instance identifier |
| `organization-id` | integer | Parent organization |
| `flexible-asset-type-id` | integer | Type definition |
| `name` | string | Auto-generated from name field |
| `traits` | object | Field values |

### Traits (Field Values)

```json
{
  "traits": {
    "primary-isp": "Comcast Business",
    "backup-isp": "Verizon FiOS",
    "public-ip-addresses": "203.0.113.10\n203.0.113.11",
    "firewall": {
      "type": "Tag",
      "values": [{"id": 12345, "type": "Configuration"}]
    },
    "dns-provider": "Cloudflare"
  }
}
```

## Critical: Discover Type IDs First

**Flexible asset type IDs are instance-specific** — every IT Glue account has different IDs. Never guess or hardcode type IDs. Always call `list_flexible_asset_types` first to discover what types exist, then use the returned IDs with `search_flexible_assets`.

```
Step 1: list_flexible_asset_types → get type IDs
Step 2: search_flexible_assets(flexible_asset_type_id=<id from step 1>)
```

## API Patterns

### List Flexible Asset Types

```http
GET /flexible-asset-types
x-api-key: YOUR_API_KEY
Content-Type: application/vnd.api+json
```

### Get Flexible Asset Type Details

```http
GET /flexible-asset-types/123
x-api-key: YOUR_API_KEY
```

**With Field Definitions:**
```http
GET /flexible-asset-types/123?include=flexible-asset-fields
```

### List Flexible Assets

```http
GET /flexible-assets
x-api-key: YOUR_API_KEY
```

**By Organization:**
```http
GET /organizations/456/relationships/flexible-assets
```

**By Type:**
```http
GET /flexible-assets?filter[flexible-asset-type-id]=123
```

**By Organization and Type:**
```http
GET /flexible-assets?filter[organization-id]=456&filter[flexible-asset-type-id]=123
```

### Get Single Flexible Asset

```http
GET /flexible-assets/789
x-api-key: YOUR_API_KEY
```

**With Includes:**
```http
GET /flexible-assets/789?include=organization,flexible-asset-type
```

### Create Flexible Asset

```http
POST /flexible-assets
Content-Type: application/vnd.api+json
x-api-key: YOUR_API_KEY
```

```json
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "organization-id": 456,
      "flexible-asset-type-id": 123,
      "traits": {
        "name": "Acme Corp Network Overview",
        "primary-isp": "Comcast Business",
        "backup-isp": "Verizon FiOS",
        "public-ip-addresses": "203.0.113.10\n203.0.113.11",
        "dns-provider": "Cloudflare"
      }
    }
  }
}
```

### Create with Tag Fields

```json
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "organization-id": 456,
      "flexible-asset-type-id": 123,
      "traits": {
        "name": "Main Office Network",
        "firewall": [12345],
        "core-switch": [67890],
        "network-admin": [11111]
      }
    }
  }
}
```

### Update Flexible Asset

```http
PATCH /flexible-assets/789
Content-Type: application/vnd.api+json
x-api-key: YOUR_API_KEY
```

```json
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "traits": {
        "backup-isp": "AT&T Business",
        "last-reviewed": "2024-02-15"
      }
    }
  }
}
```

### Delete Flexible Asset

```http
DELETE /flexible-assets/789
x-api-key: YOUR_API_KEY
```

## Common Flexible Asset Types

### Network Overview

```
Fields:
├── Name (Text) - Required, Name field
├── Primary ISP (Text)
├── Backup ISP (Text)
├── Public IP Addresses (Textarea)
├── Internal IP Scheme (Textarea)
├── Firewall (Tag - Configuration)
├── Core Switch (Tag - Configuration)
├── Network Diagram (Upload)
├── DNS Provider (Select)
└── Last Reviewed (Date)
```

### Application Documentation

```
Fields:
├── Name (Text) - Required, Name field
├── Description (Textarea)
├── Version (Text)
├── Vendor (Text)
├── Support Contact (Tag - Contact)
├── Primary Server (Tag - Configuration)
├── Database Server (Tag - Configuration)
├── Admin URL (Text)
├── Admin Credentials (Password)
├── License Key (Password)
├── License Expiration (Date)
├── Documentation URL (Text)
└── Notes (Textarea)
```

### Backup Overview

```
Fields:
├── Name (Text) - Required, Name field
├── Backup Solution (Select)
├── Backup Server (Tag - Configuration)
├── Retention Policy (Textarea)
├── Backup Schedule (Textarea)
├── Data Protected (Textarea)
├── Recovery Time Objective (Text)
├── Recovery Point Objective (Text)
├── Last Test Date (Date)
├── Backup Admin Credentials (Password)
└── Notes (Textarea)
```

### Microsoft 365 Tenant

```
Fields:
├── Name (Text) - Required, Name field
├── Tenant ID (Text)
├── Primary Domain (Text)
├── Additional Domains (Textarea)
├── License Summary (Textarea)
├── Admin Portal URL (Text)
├── Global Admin (Tag - Contact)
├── Admin Credentials (Password)
├── MFA Status (Select)
├── Conditional Access (Checkbox)
└── Notes (Textarea)
```

## Common Workflows

### Create Flexible Asset from Template

```javascript
async function createFlexibleAssetFromType(orgId, typeId, fieldValues) {
  // Get the type definition to understand fields
  const assetType = await getFlexibleAssetType(typeId, {
    include: 'flexible-asset-fields'
  });

  // Validate required fields
  const requiredFields = assetType.included?.filter(
    f => f.attributes.required
  ) || [];

  for (const field of requiredFields) {
    const fieldKey = field.attributes['name-key'];
    if (!fieldValues[fieldKey]) {
      throw new Error(`Required field missing: ${field.attributes.name}`);
    }
  }

  // Create the flexible asset
  return await createFlexibleAsset({
    'organization-id': orgId,
    'flexible-asset-type-id': typeId,
    traits: fieldValues
  });
}
```

### Find Flexible Assets by Type

```javascript
async function findFlexibleAssetsByType(orgId, typeName) {
  // First, find the type by name
  const types = await fetchFlexibleAssetTypes();
  const type = types.find(t =>
    t.attributes.name.toLowerCase() === typeName.toLowerCase()
  );

  if (!type) {
    throw new Error(`Flexible asset type not found: ${typeName}`);
  }

  // Then fetch assets of that type for the org
  return await fetchFlexibleAssets({
    filter: {
      'organization-id': orgId,
      'flexible-asset-type-id': type.id
    }
  });
}
```

### Update Tagged Resources

```javascript
async function updateFlexibleAssetTags(assetId, fieldName, newTagIds) {
  return await updateFlexibleAsset(assetId, {
    traits: {
      [fieldName]: newTagIds
    }
  });
}
```

### Export Flexible Asset Data

```javascript
async function exportFlexibleAssets(orgId, typeId) {
  const assets = await fetchFlexibleAssets({
    filter: {
      'organization-id': orgId,
      'flexible-asset-type-id': typeId
    }
  });

  const type = await getFlexibleAssetType(typeId, {
    include: 'flexible-asset-fields'
  });

  const fieldNames = type.included?.reduce((acc, f) => {
    acc[f.attributes['name-key']] = f.attributes.name;
    return acc;
  }, {}) || {};

  return assets.map(asset => {
    const exportData = { id: asset.id };
    Object.entries(asset.attributes.traits || {}).forEach(([key, value]) => {
      const fieldName = fieldNames[key] || key;
      exportData[fieldName] = value;
    });
    return exportData;
  });
}
```

### Flexible Asset Health Check

```javascript
async function flexibleAssetHealthCheck(orgId) {
  // Get all flexible asset types
  const types = await fetchFlexibleAssetTypes();

  const results = [];

  for (const type of types) {
    const assets = await fetchFlexibleAssets({
      filter: {
        'organization-id': orgId,
        'flexible-asset-type-id': type.id
      }
    });

    results.push({
      type: type.attributes.name,
      count: assets.length,
      hasAssets: assets.length > 0
    });
  }

  return {
    totalTypes: types.length,
    typesWithData: results.filter(r => r.hasAssets).length,
    details: results
  };
}
```

### Clone Flexible Asset to Another Org

```javascript
async function cloneFlexibleAsset(sourceAssetId, targetOrgId) {
  // Get source asset
  const source = await getFlexibleAsset(sourceAssetId);

  // Clone traits (remove tag fields that won't be valid in new org)
  const traits = { ...source.attributes.traits };

  // Note: Tag fields reference resources in the source org
  // You may need to map or remove these

  return await createFlexibleAsset({
    'organization-id': targetOrgId,
    'flexible-asset-type-id': source.attributes['flexible-asset-type-id'],
    traits: traits
  });
}
```

## Error Handling

### Common API Errors

| Code | Message | Resolution |
|------|---------|------------|
| 400 | Organization required | Include organization-id |
| 400 | Type required | Include flexible-asset-type-id |
| 401 | Invalid API key | Check IT_GLUE_API_KEY |
| 404 | Asset not found | Verify asset ID |
| 422 | Invalid trait value | Check field type requirements |
| 422 | Required field missing | Provide all required traits |

### Validation Errors

| Error | Cause | Fix |
|-------|-------|-----|
| Organization required | No org ID | Include organization-id |
| Type required | No type ID | Include flexible-asset-type-id |
| Invalid trait | Wrong data type | Match field type |
| Required trait | Missing required field | Add trait value |
| Invalid tag | Bad resource ID | Verify tagged resource exists |

### Error Recovery Pattern

```javascript
async function safeCreateFlexibleAsset(data) {
  try {
    return await createFlexibleAsset(data);
  } catch (error) {
    if (error.status === 422) {
      const errors = error.errors || [];

      // Handle missing required fields
      const missingFields = errors.filter(e =>
        e.detail?.includes('required') || e.detail?.includes("can't be blank")
      );

      if (missingFields.length > 0) {
        console.log('Missing required fields:',
          missingFields.map(e => e.source?.pointer)
        );

        // Get type definition to see required fields
        const type = await getFlexibleAssetType(data['flexible-asset-type-id'], {
          include: 'flexible-asset-fields'
        });
        const required = type.included?.filter(f => f.attributes.required);
        console.log('Required fields:', required?.map(f => f.attributes.name));
      }

      // Handle invalid tag references
      const invalidTags = errors.filter(e =>
        e.detail?.includes('invalid') && e.source?.pointer?.includes('traits')
      );

      if (invalidTags.length > 0) {
        console.log('Invalid tag references found. Removing...');
        // Remove invalid tags and retry
        // (implementation depends on which fields are tags)
      }
    }

    throw error;
  }
}
```

## Best Practices

1. **Plan type structure** - Design flexible asset types before creating
2. **Use consistent naming** - Follow conventions for field names
3. **Leverage tags** - Link to configurations, contacts for relationships
4. **Required fields** - Mark essential fields as required
5. **Use appropriate types** - Match field type to data (date for dates, etc.)
6. **Document types** - Add descriptions to types and fields
7. **Standardize across orgs** - Use same types for all clients
8. **Regular reviews** - Update flexible asset content periodically
9. **Avoid duplicates** - One flexible asset per topic per org
10. **Export capability** - Build export for reporting needs

## Related Skills

- [IT Glue Organizations](../organizations/SKILL.md) - Flexible asset scope
- [IT Glue Configurations](../configurations/SKILL.md) - Tag field targets
- [IT Glue Contacts](../contacts/SKILL.md) - Tag field targets
- [IT Glue Passwords](../passwords/SKILL.md) - Password fields
- [IT Glue Documents](../documents/SKILL.md) - Alternative documentation
- [IT Glue API Patterns](../api-patterns/SKILL.md) - API reference

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.