Skip to content

Product Attribute Values Guide

Overview

Product Attribute Values are the concrete data points that bind an attribute definition to a specific product. Where the Product Attributes guide explains how to create and configure attribute definitions (the schema), this guide focuses on the values stored against those definitions - querying system-wide statistics, exporting a product's full attribute profile, and comparing attribute values between two products side by side.

Attribute values live inside the Product aggregate. They are written through the standard POST /products and PUT /products/{id} endpoints covered in the Product Attributes guide. This guide covers the three read-oriented endpoints that operate on the attribute-value layer directly: statistics, export, and comparison.

Value Types

All 12 attribute types supported by the attribute definition system produce values in the attribute-value layer. Each type has its own storage representation and display formatting:

TypeStored AsgetFormattedValue() ExamplegetDisplayValue() Example
TEXTString"100% Cotton""100% Cotton"
NUMBERString (numeric)"300 threads/inch""300"
BOOLEANString ("1"/"0")"Yes""Yes"
DATEString (ISO 8601)"January 15, 2024""2024-01-15"
SELECTString"Red""Red"
MULTISELECTJSON array string"Machine Wash, Tumble Dry""Machine Wash, Tumble Dry"
COLORHex string"#FF5733""#FF5733"
IMAGEURL string"https://cdn.example.com/img.jpg""https://cdn.example.com/img.jpg"
URLURL string"https://youtube.com/watch?v=abc""https://youtube.com/watch?v=abc"
EMAILString"contact@manufacturer.com""contact@manufacturer.com"
PHONEString"+1-555-0123""+1-555-0123"
JSONJSON stringFormatted objectRaw JSON string

Values are always stored as strings internally. getFormattedValue() applies type-aware formatting for display (e.g., appending units to NUMBER types, joining MULTISELECT arrays with commas). getDisplayValue() returns a plain frontend-friendly string without additional decoration.

API Endpoints

All endpoints are under the base path /api/v1/operations.


1. Get Attribute Value Statistics

Retrieve system-wide aggregate statistics across all attribute values stored in the tenant's product catalog.

Endpoint: GET /api/v1/operations/product-attribute-values/statistics

Authentication: Required (Bearer token)

Response (200 OK):

json
{
  "success": true,
  "message": "Attribute value statistics retrieved successfully",
  "data": {
    "total_values": 8423,
    "products_with_attributes": 645,
    "average_attributes_per_product": 13.1,
    "by_type": {
      "TEXT": 2341,
      "SELECT": 1876,
      "NUMBER": 1203,
      "BOOLEAN": 987,
      "MULTISELECT": 754,
      "DATE": 412,
      "COLOR": 389,
      "URL": 201,
      "IMAGE": 148,
      "EMAIL": 67,
      "PHONE": 31,
      "JSON": 14
    }
  },
  "meta": {}
}

Response Fields:

FieldDescription
total_valuesTotal attribute-value records across all products
products_with_attributesNumber of distinct products that have at least one attribute value
average_attributes_per_productMean number of attribute values per product (includes only products that have at least one value)
by_typeCount of stored values broken down by attribute type

Usage Note

This endpoint aggregates across all products in the tenant. It is well-suited for catalog health dashboards and data completeness monitoring, not for per-product detail. To inspect values on a specific product, retrieve the product via GET /api/v1/operations/products/{id}.


2. Export Product Attribute Values

Export all attribute values for a single product as either CSV or JSON. Useful for integrations, audits, and data migrations.

Endpoint: GET /api/v1/operations/products/{id}/attribute-values/export

Authentication: Required (Bearer token)

Path Parameters:

  • id (ULID, required) - The product's ULID identifier

Query Parameters:

  • format (string, required) - Export format: csv or json

Example Requests:

bash
# Export as CSV
GET /api/v1/operations/products/01hwxyz123abc456def789ghi0/attribute-values/export?format=csv

# Export as JSON
GET /api/v1/operations/products/01hwxyz123abc456def789ghi0/attribute-values/export?format=json

Response - JSON format (200 OK):

json
{
  "success": true,
  "message": "Attribute values exported successfully",
  "data": {
    "product_id": "01hwxyz123abc456def789ghi0",
    "product_name": "Classic Cotton T-Shirt",
    "exported_at": "2026-03-11T09:00:00Z",
    "format": "json",
    "values": [
      {
        "attribute_code": "color",
        "attribute_name": "Color",
        "attribute_type": "SELECT",
        "value": "Navy",
        "formatted_value": "Navy",
        "display_value": "Navy"
      },
      {
        "attribute_code": "size",
        "attribute_name": "Size",
        "attribute_type": "SELECT",
        "value": "L",
        "formatted_value": "L",
        "display_value": "L"
      },
      {
        "attribute_code": "thread_count",
        "attribute_name": "Thread Count",
        "attribute_type": "NUMBER",
        "value": "300",
        "formatted_value": "300 threads/inch",
        "display_value": "300"
      },
      {
        "attribute_code": "organic_certified",
        "attribute_name": "Organic Certified",
        "attribute_type": "BOOLEAN",
        "value": "1",
        "formatted_value": "Yes",
        "display_value": "Yes"
      }
    ],
    "total": 4
  },
  "meta": {}
}

Response - CSV format:

For format=csv, the response body is a plain CSV file with Content-Type: text/csv and a Content-Disposition: attachment header. Columns are: attribute_code, attribute_name, attribute_type, value, formatted_value, display_value.

attribute_code,attribute_name,attribute_type,value,formatted_value,display_value
color,Color,SELECT,Navy,Navy,Navy
size,Size,SELECT,L,L,L
thread_count,Thread Count,NUMBER,300,300 threads/inch,300
organic_certified,Organic Certified,BOOLEAN,1,Yes,Yes

3. Compare Attribute Values Between Products

Compare attribute values for two products side by side. Optionally filter to only the attributes that differ between them.

Endpoint: POST /api/v1/operations/products/compare-attributes

Authentication: Required (Bearer token)

Request Body:

json
{
  "product_id_1": "01hwxyz123abc456def789ghi0",
  "product_id_2": "01hwxyz123abc456def789ghi1",
  "attribute_ids": [
    "01hwattr000000000000000001",
    "01hwattr000000000000000002",
    "01hwattr000000000000000003"
  ],
  "include_only_differences": false
}

Request Fields:

FieldTypeRequiredDescription
product_id_1ULIDYesFirst product to compare
product_id_2ULIDYesSecond product to compare
attribute_idsarrayNoLimit comparison to specific attribute ULIDs. Omit to compare all shared attributes
include_only_differencesbooleanNoWhen true, only attributes where the two products differ are returned (default: false)

Response (200 OK):

json
{
  "success": true,
  "message": "Product attributes compared successfully",
  "data": {
    "product_1": {
      "id": "01hwxyz123abc456def789ghi0",
      "name": "Classic Cotton T-Shirt - Navy L"
    },
    "product_2": {
      "id": "01hwxyz123abc456def789ghi1",
      "name": "Classic Cotton T-Shirt - Red M"
    },
    "comparison": [
      {
        "attribute_code": "color",
        "attribute_name": "Color",
        "attribute_type": "SELECT",
        "product_1_value": "Navy",
        "product_2_value": "Red",
        "is_different": true
      },
      {
        "attribute_code": "size",
        "attribute_name": "Size",
        "attribute_type": "SELECT",
        "product_1_value": "L",
        "product_2_value": "M",
        "is_different": true
      },
      {
        "attribute_code": "material",
        "attribute_name": "Material",
        "attribute_type": "TEXT",
        "product_1_value": "100% Cotton",
        "product_2_value": "100% Cotton",
        "is_different": false
      },
      {
        "attribute_code": "thread_count",
        "attribute_name": "Thread Count",
        "attribute_type": "NUMBER",
        "product_1_value": "300",
        "product_2_value": "300",
        "is_different": false
      }
    ],
    "summary": {
      "total_compared": 4,
      "differences": 2,
      "matches": 2
    }
  },
  "meta": {}
}

Business Scenarios

Scenario 1: Catalog Data Completeness Audit

Context: A catalog manager wants to understand how thoroughly the product catalog has been enriched with attribute data before launching a new storefront.

Workflow:

  1. Pull statistics to get the overall picture
  2. Calculate completeness against expected attribute count
  3. Target products below the average for enrichment
bash
# 1. Get system-wide statistics
GET /api/v1/operations/product-attribute-values/statistics

# Response shows average_attributes_per_product: 13.1
# Internal target: every product should have at least 8 attributes

# 2. Identify products that have fewer attributes than average
#    (via standard products list filtered by your own logic or a reporting tool)

# 3. Export a specific under-enriched product for offline review
GET /api/v1/operations/products/01hwxyz123abc456def789ghi0/attribute-values/export?format=csv

Scenario 2: Product Variant Verification

Context: A product team has created two variants of the same base product (e.g., a T-Shirt in two colour/size combinations) and needs to confirm only the intended attributes differ.

Workflow:

  1. Run the comparison endpoint between the two variants
  2. Use include_only_differences: true to focus on divergences
  3. Review unexpected matches or differences and correct them via product update
bash
POST /api/v1/operations/products/compare-attributes
{
  "product_id_1": "01hwxyz123abc456def789ghi0",
  "product_id_2": "01hwxyz123abc456def789ghi1",
  "include_only_differences": true
}

The response summary.differences count should equal only the number of attributes that legitimately differ between variants (e.g., color and size). If additional unexpected differences appear, update those products to align shared attribute values.


Scenario 3: Integration Data Handoff

Context: An e-commerce platform integration requires product attribute data in a structured format for catalogue synchronisation.

Workflow:

  1. For each product in scope, call the JSON export endpoint
  2. Transform the values array into the integration's expected schema
  3. Push formatted data to the downstream platform
bash
# Export all attribute values for a product as structured JSON
GET /api/v1/operations/products/01hwxyz123abc456def789ghi0/attribute-values/export?format=json

# The response `data.values` array is stable and type-annotated,
# making it straightforward to map to external schemas.

Best Practices

1. Prefer JSON Export for Programmatic Consumption

When building integrations or feeding attribute data into downstream systems, use format=json. The typed attribute_type field lets your code branch on type without needing to query the attribute definition separately. Reserve format=csv for human-readable exports and spreadsheet workflows.

2. Use include_only_differences for Variant QA

When maintaining a product catalog with many variants, the comparison endpoint with include_only_differences: true is a fast sanity check. Running it after bulk product imports can surface accidental data divergences before they reach the storefront.

3. Monitor the by_type Distribution in Statistics

A healthy catalog typically has TEXT, SELECT, and NUMBER values as its largest groups. A very high proportion of JSON values may indicate that structured data is being stuffed into JSON attributes rather than decomposed into typed fields. Revisit your attribute schema if this ratio looks unusual.

4. Write Values Through the Products API

Attribute values are managed as part of the Product aggregate - there is no standalone "create attribute value" endpoint. Always set or update values via POST /api/v1/operations/products (on create) or PUT /api/v1/operations/products/{id} (on update), using the attributes map. This ensures aggregate consistency, validation, and audit trail correctness.

Integration Points

With Product Attributes

The values described in this guide are instances of the attribute definitions managed in the Product Attributes guide. Before a value can be stored for an attribute, that attribute definition must exist. Changes to an attribute's options (e.g., adding a new SELECT value) are reflected immediately in subsequent value writes.

With Product Variants

Attribute values are the mechanism that distinguishes product variants. A variant set shares a base product but differs on one or more dimension attributes (color, size, material). The comparison endpoint is particularly valuable when verifying variant setup. Refer to the Product Variants guide for the full variant creation workflow.

With Inventory and Pricing

Attribute values feed filtering and segmentation rules in inventory management and pricing strategies. For example, a pricing rule may apply a surcharge to all products where material = "Leather", relying on the attribute value being correctly populated. Refer to the Pricing Strategy guide and Inventory Management guide.

Troubleshooting

Export Returns Empty values Array

Symptom: The export endpoint returns a 200 OK response but data.values is an empty array and data.total is 0.

Cause: The product exists but has no attribute values assigned to it yet.

Solution: Assign attribute values to the product via the Products API before exporting:

bash
PUT /api/v1/operations/products/01hwxyz123abc456def789ghi0
{
  "attributes": {
    "color": "Navy",
    "size": "L",
    "material": "100% Cotton"
  }
}

Comparison Returns null for One Product's Value

Symptom: A comparison row shows "product_1_value": "Red" but "product_2_value": null.

Cause: The second product does not have a value stored for that attribute, even though the attribute definition exists.

Solution: Check the second product's attribute values and populate any missing ones:

bash
GET /api/v1/operations/products/01hwxyz123abc456def789ghi1/attribute-values/export?format=json

Review the response to identify which attributes are absent, then update the product with the missing values.


Documentation for SynthesQ CRM/ERP Platform