Skip to content

Product Attributes Guide

Overview

The Product Attributes system allows you to define and manage dynamic, flexible attributes for products through the REST API. This guide covers attribute types, validation rules, API endpoints, and best practices for using attributes to create rich product catalogs.

Understanding Product Attributes

What are Product Attributes?

Product attributes are customizable properties that provide detailed product information beyond basic fields like name and SKU. Examples include:

  • Color: Red, Blue, Green
  • Size: XS, S, M, L, XL
  • Material: Cotton, Polyester, Leather
  • Technical Specs: Screen size, battery life, processor type
  • Certifications: Organic, Fair Trade, OEKO-TEX

EAV Pattern (Entity-Attribute-Value)

The system uses the EAV pattern to provide flexibility without changing the database schema:

  • Entity: The product (e.g., "Cotton T-Shirt")
  • Attribute: The attribute definition (e.g., "Color" with type SELECT)
  • Value: The specific value for this product (e.g., "Red")

Benefits:

  • ✅ Add new attributes without database changes
  • ✅ Different products can have different attributes
  • ✅ Type-safe validation (numbers, dates, booleans, etc.)
  • ✅ Flexible filtering and search capabilities
  • ✅ Support for single-select, multi-select, and complex data types

Attribute Types

Supported Types

The system supports 12 attribute types:

TypeDescriptionExample ValueUse Case
TEXTShort text"Cotton blend"Materials, descriptions
NUMBERNumeric value42Dimensions, counts, weights
BOOLEANYes/NotrueFeatures (waterproof, organic)
DATECalendar date"2024-12-31"Expiry dates, release dates
SELECTSingle choice"Red"Color, size, fit
MULTISELECTMultiple choices["Red", "Blue"]Features, certifications
COLORHex color"#FF0000"Color swatches
IMAGEImage URL"https://..."Additional product images
URLWeb address"https://..."Video links, manuals
EMAILEmail address"user@example.com"Manufacturer contacts
PHONEPhone number"+1-555-1234"Support numbers
JSONStructured dataComplex specifications

Type Capabilities

Searchable Types: TEXT, SELECT, MULTISELECT

  • Can be searched using text queries

Filterable Types: BOOLEAN, SELECT, MULTISELECT, COLOR, NUMBER

  • Can be used to filter product catalogs

Sortable Types: TEXT, NUMBER, DATE

  • Can be used to sort product listings

API Endpoints

Base path: /api/v1/operations/attributes

1. List Attribute Types

Get all available attribute types with their metadata.

Endpoint: GET /api/v1/operations/attributes/types

Response (200 OK):

json
{
  "data": [
    {
      "value": "text",
      "label": "Text",
      "has_options": false,
      "is_searchable": true,
      "is_filterable": false,
      "is_sortable": true,
      "input_type": "text",
      "default_validation": []
    },
    {
      "value": "select",
      "label": "Single Select",
      "has_options": true,
      "is_searchable": true,
      "is_filterable": true,
      "is_sortable": false,
      "input_type": "select",
      "default_validation": []
    },
    {
      "value": "number",
      "label": "Number",
      "has_options": false,
      "is_searchable": false,
      "is_filterable": true,
      "is_sortable": true,
      "input_type": "number",
      "default_validation": ["numeric"]
    }
  ]
}

2. Create Attribute Definition

Define a new attribute template that products can use.

Endpoint: POST /api/v1/operations/attributes

Request Body (TEXT attribute):

json
{
  "code": "material",
  "name": "Material",
  "label": "Product Material",
  "type": "text",
  "description": "Primary material composition",
  "is_required": false,
  "is_filterable": true,
  "is_searchable": true,
  "is_visible_on_frontend": true,
  "sort_order": 10
}

Request Body (SELECT attribute with options):

json
{
  "code": "size",
  "name": "Size",
  "label": "Product Size",
  "type": "select",
  "description": "Available product sizes",
  "options": ["XS", "S", "M", "L", "XL", "XXL"],
  "is_required": true,
  "is_filterable": true,
  "is_searchable": true,
  "is_visible_on_frontend": true,
  "sort_order": 5
}

Request Body (NUMBER attribute with unit):

json
{
  "code": "thread_count",
  "name": "Thread Count",
  "label": "Fabric Thread Count",
  "type": "number",
  "unit": "threads/inch",
  "description": "Fabric density measurement",
  "validation_rules": ["min:100", "max:1000"],
  "is_required": false,
  "is_filterable": true,
  "is_visible_on_frontend": true,
  "sort_order": 15,
  "default_value": 200
}

Response (201 Created):

json
{
  "message": "Attribute created successfully",
  "data": {
    "id": 5,
    "code": "material",
    "name": "Material",
    "label": "Product Material",
    "type": "text",
    "description": "Primary material composition",
    "options": null,
    "validation_rules": null,
    "is_required": false,
    "is_filterable": true,
    "is_searchable": true,
    "is_visible_on_frontend": true,
    "sort_order": 10,
    "unit": null,
    "default_value": null,
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Validation Rules:

  • code: Required, unique, max 100 chars, alphanumeric with dashes/underscores only
  • name: Required, max 255 chars
  • label: Required, max 255 chars
  • type: Required, must be valid attribute type
  • options: Required for SELECT and MULTISELECT types
  • is_required: Boolean (default: false)
  • is_filterable: Boolean (default: false)
  • is_searchable: Boolean (default: false)
  • is_visible_on_frontend: Boolean (default: true)
  • sort_order: Integer, min 0 (default: 0)

Business Rules:

  • Attribute code must be unique and cannot be changed after creation
  • SELECT and MULTISELECT types require an options array
  • Attribute codes should use lowercase with underscores (e.g., "thread_count", "eco_friendly")

3. Update Attribute Definition

Update an existing attribute definition.

Endpoint: PUT /api/v1/operations/attributes/{attribute}

Request Body:

json
{
  "name": "Product Size",
  "label": "Choose Size",
  "options": ["XS", "S", "M", "L", "XL", "XXL", "XXXL"],
  "is_required": true,
  "sort_order": 3
}

Response (200 OK):

json
{
  "message": "Attribute updated successfully",
  "data": {
    "id": 5,
    "code": "size",
    "name": "Product Size",
    "options": ["XS", "S", "M", "L", "XL", "XXL", "XXXL"],
    "is_required": true,
    "sort_order": 3
  }
}

Important: Cannot change code or type after creation. Only metadata and options can be updated.


4. List All Attributes

Get paginated list of attribute definitions.

Endpoint: GET /api/v1/operations/attributes

Query Parameters:

  • page: Page number (default: 1)
  • per_page: Items per page (default: 50, max: 100)
  • type: Filter by attribute type (select, text, etc.)
  • filterable: Filter to only filterable attributes (true/false)
  • searchable: Filter to only searchable attributes (true/false)
  • required: Filter to only required attributes (true/false)

Response (200 OK):

json
{
  "data": [
    {
      "id": 1,
      "code": "color",
      "name": "Color",
      "type": "select",
      "options": ["Red", "Blue", "Green"],
      "is_required": true,
      "is_filterable": true,
      "is_searchable": true
    },
    {
      "id": 2,
      "code": "material",
      "name": "Material",
      "type": "text",
      "is_required": false,
      "is_filterable": true,
      "is_searchable": true
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 50,
    "total": 2,
    "last_page": 1
  }
}

5. Get Single Attribute

Retrieve detailed information about a specific attribute.

Endpoint: GET /api/v1/operations/attributes/{attribute}

Response (200 OK):

json
{
  "data": {
    "id": 5,
    "code": "size",
    "name": "Size",
    "label": "Product Size",
    "type": "select",
    "description": "Available product sizes",
    "options": ["XS", "S", "M", "L", "XL", "XXL"],
    "validation_rules": null,
    "is_required": true,
    "is_filterable": true,
    "is_searchable": true,
    "is_visible_on_frontend": true,
    "sort_order": 5,
    "unit": null,
    "default_value": null,
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T12:45:00Z",
    "values_count": 147
  }
}

6. Delete Attribute

Delete an attribute definition.

Endpoint: DELETE /api/v1/operations/attributes/{attribute}

Response (200 OK):

json
{
  "message": "Attribute deleted successfully"
}

Business Rules:

  • Cannot delete required attributes that are currently assigned to products
  • Deleting an attribute removes all associated values from products
  • Deleted attributes can be restored (soft delete)

7. Get Attribute Statistics

Get usage statistics for all attributes.

Endpoint: GET /api/v1/operations/attributes/statistics

Response (200 OK):

json
{
  "data": {
    "total_attributes": 12,
    "by_type": {
      "text": 4,
      "select": 3,
      "number": 2,
      "boolean": 2,
      "color": 1
    },
    "required_count": 5,
    "filterable_count": 8,
    "searchable_count": 6,
    "most_used": [
      {
        "id": 1,
        "code": "color",
        "name": "Color",
        "products_count": 247
      },
      {
        "id": 2,
        "code": "size",
        "name": "Size",
        "products_count": 198
      }
    ]
  }
}

Assigning Attributes to Products

Setting Product Attributes

Attributes are assigned when creating or updating products. Include attribute values in the attributes field.

Create Product with Attributes:

json
POST /api/v1/operations/products
{
  "name": "Cotton T-Shirt",
  "sku": "TSHIRT-001",
  "selling_price": 24.99,
  "cost_price": 12.00,
  "currency": "USD",
  "attributes": {
    "color": "Blue",
    "size": "Large",
    "material": "100% Cotton",
    "eco_friendly": true,
    "thread_count": 300
  }
}

Update Product Attributes:

json
PUT /api/v1/operations/products/123
{
  "attributes": {
    "color": "Red",
    "size": "Medium"
  }
}

Response (200 OK):

json
{
  "message": "Product updated successfully",
  "data": {
    "id": 123,
    "name": "Cotton T-Shirt",
    "attributes": {
      "color": "Red",
      "size": "Medium",
      "material": "100% Cotton",
      "eco_friendly": true,
      "thread_count": 300
    }
  }
}

Retrieving Product Attributes

Get Product with Attributes:

bash
GET /api/v1/operations/products/123

Response:

json
{
  "data": {
    "id": 123,
    "name": "Cotton T-Shirt",
    "sku": "TSHIRT-001",
    "attributes": {
      "color": "Red",
      "size": "Medium",
      "material": "100% Cotton",
      "eco_friendly": true,
      "thread_count": 300
    },
    "visible_attributes": [
      {
        "code": "color",
        "name": "Color",
        "label": "Product Color",
        "value": "Red",
        "formatted_value": "Red",
        "type": "select"
      },
      {
        "code": "thread_count",
        "name": "Thread Count",
        "label": "Fabric Thread Count",
        "value": 300,
        "formatted_value": "300 threads/inch",
        "type": "number",
        "unit": "threads/inch"
      }
    ]
  }
}

Attribute Type Examples

TEXT Attribute

Definition:

json
{
  "code": "product_description",
  "name": "Description",
  "type": "text",
  "is_required": false
}

Usage:

json
{
  "attributes": {
    "product_description": "Soft and comfortable cotton t-shirt"
  }
}

NUMBER Attribute

Definition:

json
{
  "code": "weight_kg",
  "name": "Weight",
  "type": "number",
  "unit": "kg",
  "validation_rules": ["min:0", "max:1000"]
}

Usage:

json
{
  "attributes": {
    "weight_kg": 2.5
  }
}

BOOLEAN Attribute

Definition:

json
{
  "code": "organic_certified",
  "name": "Organic Certified",
  "type": "boolean",
  "default_value": false
}

Usage:

json
{
  "attributes": {
    "organic_certified": true
  }
}

DATE Attribute

Definition:

json
{
  "code": "manufacture_date",
  "name": "Manufacture Date",
  "type": "date"
}

Usage:

json
{
  "attributes": {
    "manufacture_date": "2024-01-15"
  }
}

Note: Use ISO 8601 format (YYYY-MM-DD).


SELECT Attribute

Definition:

json
{
  "code": "fit",
  "name": "Fit",
  "type": "select",
  "options": ["Slim", "Regular", "Relaxed", "Oversized"],
  "is_required": true
}

Usage:

json
{
  "attributes": {
    "fit": "Regular"
  }
}

Validation: Value must be one of the options. Invalid values will return a 422 error:

json
{
  "errors": {
    "attributes.fit": [
      "Value 'Extra Slim' is not valid for attribute 'Fit'. Allowed values: Slim, Regular, Relaxed, Oversized"
    ]
  }
}

MULTISELECT Attribute

Definition:

json
{
  "code": "care_instructions",
  "name": "Care Instructions",
  "type": "multiselect",
  "options": [
    "Machine Wash",
    "Hand Wash",
    "Dry Clean Only",
    "Tumble Dry",
    "Air Dry",
    "Iron Low Heat"
  ]
}

Usage:

json
{
  "attributes": {
    "care_instructions": [
      "Machine Wash",
      "Tumble Dry",
      "Iron Low Heat"
    ]
  }
}

Note: Value must be an array. All values must exist in the options list.


COLOR Attribute

Definition:

json
{
  "code": "primary_color_hex",
  "name": "Primary Color",
  "type": "color"
}

Usage:

json
{
  "attributes": {
    "primary_color_hex": "#FF5733"
  }
}

Validation: Must be valid hex color (e.g., #FF5733, #000000).


URL Attribute

Definition:

json
{
  "code": "product_video",
  "name": "Product Video",
  "type": "url"
}

Usage:

json
{
  "attributes": {
    "product_video": "https://youtube.com/watch?v=abc123"
  }
}

EMAIL Attribute

Definition:

json
{
  "code": "manufacturer_contact",
  "name": "Manufacturer Contact",
  "type": "email"
}

Usage:

json
{
  "attributes": {
    "manufacturer_contact": "contact@manufacturer.com"
  }
}

JSON Attribute

Definition:

json
{
  "code": "technical_specs",
  "name": "Technical Specifications",
  "type": "json"
}

Usage:

json
{
  "attributes": {
    "technical_specs": {
      "processor": "A17 Pro",
      "ram": "8GB",
      "storage": "256GB",
      "camera": "48MP"
    }
  }
}

Note: Value can be any valid JSON object or array.


Validation & Business Rules

Automatic Validation

Each attribute type has built-in validation:

TEXT:

  • Maximum 255 characters
  • String validation

NUMBER:

  • Must be numeric
  • Supports min/max validation rules

BOOLEAN:

  • Must be true or false

DATE:

  • Must be valid date in YYYY-MM-DD format

SELECT:

  • Value must exist in options array
  • Only one value allowed

MULTISELECT:

  • Value must be array
  • All values must exist in options array

COLOR:

  • Must be valid hex color (#RRGGBB)

EMAIL:

  • Must be valid email format

URL:

  • Must be valid URL format

PHONE:

  • Must be valid phone number format

JSON:

  • Must be valid JSON

Custom Validation Rules

You can add Laravel validation rules to attributes:

Example:

json
{
  "code": "discount_percentage",
  "name": "Discount Percentage",
  "type": "number",
  "validation_rules": ["min:0", "max:100"],
  "unit": "%"
}

Valid:

json
{
  "attributes": {
    "discount_percentage": 15
  }
}

Invalid (422 error):

json
{
  "attributes": {
    "discount_percentage": 150
  }
}

Required Attributes

Mark attributes as required to enforce product data quality:

Define Required Attribute:

json
{
  "code": "color",
  "name": "Color",
  "type": "select",
  "is_required": true,
  "options": ["Red", "Blue", "Green"]
}

Validation: Products cannot be created or activated without all required attributes set.

Error Response (422):

json
{
  "errors": {
    "attributes": [
      "Missing required attributes: Color, Size"
    ]
  }
}

Common Use Cases

Use Case 1: Apparel Attributes

Define Attributes:

json
# Size
POST /api/v1/operations/attributes
{
  "code": "size",
  "name": "Size",
  "type": "select",
  "options": ["XS", "S", "M", "L", "XL", "XXL"],
  "is_required": true,
  "is_filterable": true
}

# Color
POST /api/v1/operations/attributes
{
  "code": "color",
  "name": "Color",
  "type": "select",
  "options": ["Black", "White", "Navy", "Gray", "Red"],
  "is_required": true,
  "is_filterable": true
}

# Material
POST /api/v1/operations/attributes
{
  "code": "material",
  "name": "Material",
  "type": "text",
  "is_searchable": true
}

Create Product:

json
POST /api/v1/operations/products
{
  "name": "Classic Cotton T-Shirt",
  "sku": "TSHIRT-001",
  "selling_price": 24.99,
  "attributes": {
    "size": "L",
    "color": "Navy",
    "material": "100% Cotton",
    "care_instructions": ["Machine Wash", "Tumble Dry"]
  }
}

Use Case 2: Electronics Specifications

Define JSON Attribute:

json
POST /api/v1/operations/attributes
{
  "code": "tech_specs",
  "name": "Technical Specifications",
  "type": "json"
}

Create Product:

json
POST /api/v1/operations/products
{
  "name": "Smartphone Pro",
  "sku": "PHONE-001",
  "selling_price": 999.00,
  "attributes": {
    "tech_specs": {
      "processor": "Apple A17 Pro",
      "ram": "8GB",
      "storage": "256GB",
      "display": "6.1\" Super Retina XDR",
      "camera": "48MP Main + 12MP Ultra Wide",
      "battery": "3877 mAh",
      "connectivity": "5G, WiFi 6E, Bluetooth 5.3"
    }
  }
}

Use Case 3: Product Certifications

Define MULTISELECT Attribute:

json
POST /api/v1/operations/attributes
{
  "code": "certifications",
  "name": "Certifications",
  "type": "multiselect",
  "options": [
    "Organic Certified",
    "Fair Trade",
    "GOTS",
    "OEKO-TEX",
    "B Corp"
  ]
}

Create Product:

json
POST /api/v1/operations/products
{
  "name": "Organic Cotton Sheet Set",
  "sku": "SHEET-001",
  "selling_price": 149.99,
  "attributes": {
    "certifications": [
      "Organic Certified",
      "Fair Trade",
      "GOTS"
    ]
  }
}

Best Practices

1. Use Consistent Attribute Codes

Always use lowercase with underscores:

json
"product_color"
"thread_count"
"eco_friendly"

"ProductColor"
"Thread-Count"
"EcoFriendly"

2. Define All Options for SELECT Types

json
✅ Correct:
{
  "type": "select",
  "options": ["Red", "Blue", "Green", "Black", "White"]
}

❌ Wrong:
{
  "type": "select",
  "options": null
}

3. Use Appropriate Types

Match the attribute type to the data:

json
✅ Use BOOLEAN for yes/no:
{
  "attributes": {
    "waterproof": true
  }
}

❌ Don't use TEXT for boolean data:
{
  "attributes": {
    "waterproof": "yes"
  }
}

4. Mark Important Attributes as Required

Ensure data quality by requiring essential attributes:

json
{
  "code": "size",
  "is_required": true
}

5. Make Attributes Filterable for Catalog

Enable filtering for attributes used in product browsing:

json
{
  "code": "color",
  "is_filterable": true,
  "is_searchable": true
}

6. Use Frontend Visibility Appropriately

Hide internal attributes from frontend display:

json
{
  "code": "supplier_code",
  "is_visible_on_frontend": false
}

7. Order Attributes Logically

Use sort_order to control display sequence:

json
{
  "code": "color",
  "sort_order": 1
},
{
  "code": "size",
  "sort_order": 2
},
{
  "code": "material",
  "sort_order": 3
}

Troubleshooting

Error: "Validation failed for attribute"

Error Response:

json
{
  "errors": {
    "attributes.size": [
      "Value 'XXL' is not valid for attribute 'Size'. Allowed values: XS, S, M, L, XL"
    ]
  }
}

Solution: Add the value to attribute options:

json
PUT /api/v1/operations/attributes/5
{
  "options": ["XS", "S", "M", "L", "XL", "XXL"]
}

Error: "Missing required attributes"

Error Response:

json
{
  "errors": {
    "attributes": [
      "Missing required attributes: Color, Size"
    ]
  }
}

Solution: Include all required attributes in the request:

json
{
  "attributes": {
    "color": "Red",
    "size": "Large"
  }
}

Error: "Options required for SELECT type"

Error Response:

json
{
  "errors": {
    "options": [
      "Options are required for SELECT and MULTISELECT attribute types"
    ]
  }
}

Solution: Always provide options for SELECT/MULTISELECT:

json
{
  "type": "select",
  "options": ["Option 1", "Option 2", "Option 3"]
}

Documentation for SynthesQ CRM/ERP Platform