it-glue-flexible-assets

star 28

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.

wyre-technology By wyre-technology schedule Updated 4/5/2026

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)

{
  "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

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

Get Flexible Asset Type Details

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

With Field Definitions:

GET /flexible-asset-types/123?include=flexible-asset-fields

List Flexible Assets

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

By Organization:

GET /organizations/456/relationships/flexible-assets

By Type:

GET /flexible-assets?filter[flexible-asset-type-id]=123

By Organization and Type:

GET /flexible-assets?filter[organization-id]=456&filter[flexible-asset-type-id]=123

Get Single Flexible Asset

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

With Includes:

GET /flexible-assets/789?include=organization,flexible-asset-type

Create Flexible Asset

POST /flexible-assets
Content-Type: application/vnd.api+json
x-api-key: YOUR_API_KEY
{
  "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

{
  "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

PATCH /flexible-assets/789
Content-Type: application/vnd.api+json
x-api-key: YOUR_API_KEY
{
  "data": {
    "type": "flexible-assets",
    "attributes": {
      "traits": {
        "backup-isp": "AT&T Business",
        "last-reviewed": "2024-02-15"
      }
    }
  }
}

Delete Flexible Asset

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

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

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

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

Export Flexible Asset Data

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

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

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

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

Install via CLI
npx skills add https://github.com/wyre-technology/msp-claude-plugins --skill it-glue-flexible-assets
Repository Details
star Stars 28
call_split Forks 17
navigation Branch main
article Path SKILL.md
More from Creator
wyre-technology
wyre-technology Explore all skills →