# Working with product models using the API

## Getting started

Below is an example in JSON format, showcasing the size of the product structure model when attempting to create one through the `/v1/productstructures` endpoint.

{% tabs %}
{% tab title="HTTP" %}
**POST** /v1/productstructures
{% endtab %}

{% tab title="Request body (json)" %}

```

  "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "Alias": "string",
  "Label": "string",
  "HasVariants": true,
  "HasVariantGroups": true,
  "ProductConfiguration": {
    "ThumbnailReference": "string",
    "NameConfiguration": {
      "NamePattern": "string",
      "NameAttributes": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ]
    },
    "CreateWizard": {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Steps": [
        {
          "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "Headline": "string",
          "Description": "string"
        }
      ]
    },
    "CopyWizard": {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Steps": [
        {
          "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "Headline": "string",
          "Description": "string"
        }
      ]
    },
    "Tabs": [
      {
        "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "ViewPermission": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "SavePermission": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    ]
  },
  "VariantGroupConfiguration": {
    "GroupingAttributes": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "ThumbnailReference": "string",
    "NameConfiguration": {
      "NamePattern": "string",
      "NameAttributes": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ]
    },
    "CreateWizard": {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Steps": [
        {
          "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "Headline": "string",
          "Description": "string"
        }
      ]
    },
    "CopyWizard": {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Steps": [
        {
          "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "Headline": "string",
          "Description": "string"
        }
      ]
    },
    "Tabs": [
      {
        "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "ViewPermission": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "SavePermission": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    ]
  },
  "VariantConfiguration": {
    "ThumbnailReference": "string",
    "CreateWizard": {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Steps": [
        {
          "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
          "Headline": "string",
          "Description": "string"
        }
      ]
    },
    "Tabs": [
      {
        "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "ViewPermission": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "SavePermission": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    ]
  },
  "VariationDefinitions": [
    {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Alias": "string",
      "Name": "string",
      "NameConfiguration": {
        "NamePattern": "string",
        "NameAttributes": [
          "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        ]
      },
      "DefiningAttributes": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ],
      "SortOrder": 0
    }
  ],
  "AlwaysOnDefiningAttributes": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  ],
  "ProductIdentifierDefinitions": [
    {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Alias": "string",
      "IdentifierPattern": "string",
      "IdentifierAttributes": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ]
    }
  ],
  "VariantGroupIdentifierDefinitions": [
    {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Alias": "string",
      "IdentifierPattern": "string",
      "IdentifierAttributes": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ]
    }
  ],
  "VariantIdentifierDefinitions": [
    {
      "Uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "Alias": "string",
      "IdentifierPattern": "string",
      "IdentifierAttributes": [
        "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}

There is a lot to digest and in the following segment we will break the model into smaller pieces making it easier to digest. To start off, we will demonstrate a general example where we focus on configuring the layout of products under the product structure.\
\
For a more detailed explanation of each property and their child attributes you can read the API documentation for the [ProductStructure-endpoints](https://docs.struct.com/api-reference/endpoints/productstructures#post-v1-productstructures).

### Product structure model

{% code title="C#" overflow="wrap" %}

```csharp
public class ProductStructure
{
    public Guid Uid { get; set; }

    public string? Alias { get; set; }

    public string? Label { get; set; }

    public bool HasVariants { get; set; }

    public bool HasVariantGroups { get; set; }

    public ProductConfiguration? ProductConfiguration { get; set; }

    public VariantGroupConfiguration? VariantGroupConfiguration { get; set; }

    public VariantConfiguration? VariantConfiguration { get; set; }

    public List<VariationDefinition>? VariationDefinitions { get; set; }

    public List<Guid>? AlwaysOnDefiningAttributes { get; set; }

    public List<IdentifierDefinition>? ProductIdentifierDefinitions { get; set; }

    public List<IdentifierDefinition>? VariantGroupIdentifierDefinitions { get; set; }

    public List<IdentifierDefinition>? VariantIdentifierDefinitions { get; set; }
}
```

{% endcode %}

Above you can see the class `ProductStructure` and all the content within. Not all is required for setting up a product structure. \
\
We begin by creating an instance of the class `ProductStructure` and defining the `label` and `alias`, along with a unique `Uid` so that it is easily identifiable. As this structure does not contain variants, `HasVariants` and `HasVariantGroups` are set to `false`.

{% code title="C#" overflow="wrap" %}

```csharp
ProductStructure productStructure = new ProductStructure()
{
    Uid = Guid.NewGuid(),
    Alias = "ClothingDemo",
    Label = "ClothingDemo",
    HasVariants = false,
    HasVariantGroups = false,

    ProductConfiguration = new ProductConfiguration
    {
        ...
    },
    ...
}
```

{% endcode %}

### Product configuration

Setting up ProductConfiguration will define the layout of the products following this structure. The properties you will be working with here are:

* `ThumbnailReference`: Refers to a media attribute which holds image the image which should be presented as thumbnail for the product.
* `NameConfiguration`: Contains NamePattern and NameAttributes which will define how names are generated for products following this structure.
* `CreateWizard`: Step wizard presentation for data fulfillment when creating a product following this structure.
* `CopyWizard`: Step wizard presentation for data fulfillment when copying a product following this structure.
* `Tabs`: Contains the tabs which shall be shown on products following this product configuration in the backoffice. Also contains `sections` which contains the properties that should be displayed on each product.

To keep the example simple the wizard properties will not be used along with the thumbnail reference.

### Name configuration

{% code title="C#" overflow="wrap" %}

```csharp
ProductConfiguration = new ProductConfiguration
{
    NameConfiguration = new NameConfiguration
    {
        NamePattern = "{0} - {1}",
        NameAttributes = new List<Guid> 
        { 
            new Guid("74a43fc6-63b1-4743-aa1e-816a8133b4c1"),
            new Guid("de5572ed-1fb5-4192-a9ca-db73140f4cf5") 
        }
    },
    ...
}
```

{% endcode %}

The property  `NameConfiguration` consists of a [name pattern](#user-content-fn-1)[^1] along with a list of named attributes. Together they define how each product should be named and it is important for the `NamePattern` to match the number of attributes in `NameAttributes` as seen in the example above.&#x20;

The `Guid` assigned is a previously created attribute which we have fetched using the following Attributes endpoint [/v1/attributes](https://docs.struct.com/api-reference/endpoints/attributes#get-v1-attributes).

### Tabs

{% code title="C#" overflow="wrap" %}

```csharp
Tabs = new List<TabSetup>
{
    new DynamicTabSetup
    {
        Uid = Guid.NewGuid(),
        Label = "General",
        Sections = new List<SectionSetup>
        {
            ...
        }
    },
    ...
}
```

{% endcode %}

After setting up the `NameConfiguration`, the next step is to define the **tabs** and their layout.

Since `TabSetup` is an abstract class, you must use a class that inherits from it. In this case, we use `DynamicTabSetup`, which defines the layout of a single tab.

Each tab must be uniquely identifiable, which is done by assigning a new `Guid` to the `Uid` property. The visible name of the tab is defined through the `Label` property. Inside each tab, we configure one or more sections using the `Sections` property.

Here is an example setup:

{% code title="C#" overflow="wrap" %}

```csharp
Tabs = new List<TabSetup>
{
    new DynamicTabSetup
    {
        Uid = Guid.NewGuid(),
        Label = "General",
        Sections = new List<SectionSetup>
        {
            new DynamicSectionSetup
            {
                Uid = Guid.NewGuid(),
                Headline = "General information",
                Properties = new List<PropertySetup>
                {
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("de5572ed-1fb5-4192-a9ca-db73140f4cf5") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("c28af57f-7f8e-413c-909b-fea67ef42b25") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("74a43fc6-63b1-4743-aa1e-816a8133b4c1") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("f886acd6-1397-4004-aba0-a3b2d6180151") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("2c19e970-77e2-45db-9508-925082684081") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("e2342c65-3def-4f57-9fe7-3fe9d3f093ed") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("04b4f1b6-7240-44ac-a631-bca618c0f8b8") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("45e8b8b2-bf4a-4c85-92c9-db70cedcac9a"), ReadOnly = true },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("ccfcffdf-236a-4740-9009-c7cb25365a27") },
                    new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("a7522788-ad62-4759-83a6-d8ef2bdb75db") }
                }
            },
            ...
        }
    },
    ...
}
```

{% endcode %}

### Sections

Setting up a section is similar to setting up a tab. The main differences are:

* A section uses the `Headline` property instead of `Label`.
* Sections define a list of properties, each of which maps to a specific attribute.

Each property within a section is configured using a class such as `AttributeSetup`, and references an attribute via its `AttributeUid`. These attribute UIDs can be retrieved using the **Attributes** endpoint from the API.

When defining a property, you can also configure the behavior through the following properties:

* `ReadOnly`
* `Mandatory`
* `Unchangeable`
* `Inherits`

These are all boolean values that control how the property behaves in the UI. In the example above, we have set `ReadOnly = true` on one of the properties.

Each property also gets a unique `Uid`.&#x20;

Once you have defined the layout for one tab, adding additional tabs follow the same structure. Here is an example of what it would look like with multiple tabs:

{% code title="C#" overflow="wrap" %}

```csharp
ProductStructure productStructure = new ProductStructure()
{
    Uid = Guid.NewGuid(),
    Alias = "ClothingDemo",
    Label = "ClothingDemo",
    HasVariants = false,
    HasVariantGroups = false,

    ProductConfiguration = new ProductConfiguration
    {
        NameConfiguration = new NameConfiguration
        {
            NamePattern = "{0} - {1}",
            NameAttributes = new List<Guid> 
            { 
                new Guid("74a43fc6-63b1-4743-aa1e-816a8133b4c1"),
                new Guid("de5572ed-1fb5-4192-a9ca-db73140f4cf5") 
            }
        },
        Tabs = new List<TabSetup>
        {
            new DynamicTabSetup
            {
                Uid = Guid.NewGuid(),
                Label = "General",
                Sections = new List<SectionSetup>
                {

                    new DynamicSectionSetup
                    {
                        Uid = Guid.NewGuid(),
                        Headline = "General information",
                        Properties = new List<PropertySetup>
                        {
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("de5572ed-1fb5-4192-a9ca-db73140f4cf5") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("c28af57f-7f8e-413c-909b-fea67ef42b25") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("74a43fc6-63b1-4743-aa1e-816a8133b4c1") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("f886acd6-1397-4004-aba0-a3b2d6180151") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("2c19e970-77e2-45db-9508-925082684081") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("e2342c65-3def-4f57-9fe7-3fe9d3f093ed") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("04b4f1b6-7240-44ac-a631-bca618c0f8b8") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("45e8b8b2-bf4a-4c85-92c9-db70cedcac9a"), ReadOnly = true },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("ccfcffdf-236a-4740-9009-c7cb25365a27") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("a7522788-ad62-4759-83a6-d8ef2bdb75db") }
                        }
                    },
                    ...
                }
            },
            new DynamicTabSetup
            {
                Uid = Guid.NewGuid(),
                Label = "Media",
                Sections = new List<SectionSetup>
                {
                    new DynamicSectionSetup
                    {
                        Uid = Guid.NewGuid(),
                        Headline = "Images",
                        Properties = new List<PropertySetup>
                        {
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("2380b93c-9a98-4321-a18e-dabb628e5958") },
                            new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("80156c4b-bd7f-447d-b8ea-93d84da86a87") }
                        }
                    },
                    ...
                }
            },
            ...
        }
    },
    ...
}
```

{% endcode %}

From here we can proceed to define the product identifier definitions. The definition will configure how the identifiers of products following the structure should be generated.

### Product identifier definitions

Now we just need to add the `ProductIdentifierDefinitions`, where we configure the identifier(s) for the products using this product structure.

{% code title="C#" overflow="wrap" %}

```csharp
ProductIdentifierDefinitions = new List<IdentifierDefinition>
{
    new IdentifierDefinition
    {
        Uid = Guid.NewGuid(),
        Alias = "ModelNumber",
        IdentifierPattern = "{0}",
        IdentifierAttributes = new List<Guid>
        {
            new Guid("74a43fc6-63b1-4743-aa1e-816a8133b4c1")
        }
    }
},
```

{% endcode %}

In the example above, we have added a `ProductIdentifierDefinitions` collection containing a single `IdentifierDefinition`.

Each identifier definition includes:

* A unique `Uid`
* An `Alias` to distinguish it from other definitions
* An `IdentifierPattern` used to construct the identifier string
* A list of `IdentifierAttributes` whose values are used in the pattern

In this case, the pattern is simply `{0}`, and the single attribute used is the one with the GUID `74a43fc6-63b1-4743-aa1e-816a8133b4c1`, which represents the ModelNumber attribute in the PIM. This means the generated product identifier will directly reflect the value of the ModelNumber attribute.

With this you now have a model setup which you can use to create a product structure inside the PIM.

{% hint style="info" %}
**Tip** identifiers must be unique across value and alias. So be mindful when choosing the alias, identifier pattern and identifier attributes to avoid collisions.
{% endhint %}

## Example of wizard use and permission

In this section, we will demonstrate how to configure both the `CreateWizard` and `CopyWizard` for guiding the user when creating or copying a product in backoffice. We will also cover the use and set up of view and save permissions on individual tabs.

### Wizard create and copy

The step wizard setup enables a guided, step-by-step flow for entering product data. This improves data consistency and user experience in the PIM backoffice.

Both `CreateWizard` and `CopyWizard` share the same structure, so we will focus on the `CreateWizard` example below:

<pre class="language-csharp" data-title="C#" data-overflow="wrap"><code class="lang-csharp">ProductConfiguration = new ProductConfiguration
{
    NameConfiguration = new NameConfiguration
    {
        NamePattern = "{0}",
        NameAttributes = new List&#x3C;Guid>
        { 
            new Guid("de5572ed-1fb5-4192-a9ca-db73140f4cf5")
        }
    },
    CreateWizard = new WizardSetup
    {
        Uid = Guid.NewGuid(),
        Steps = new List&#x3C;WizardStepSetup>
        {
            new DynamicWizardStepSetup
            {
                Uid = Guid.NewGuid(),
                Headline = "Step 1",
                Description = "Basic product details",
                Properties = new List&#x3C;WizardPropertySetup>
                {
                    new AttributeWizardPropertySetup
                    {
                        Uid = new Guid("30995d23-9492-4467-ab13-faa565afd579"),
                        PropertyUid = newGuid, Mandatory = true
                    },
                    ...
                }
            },
            ...
        }
    },
    CopyWizard = new WizardSetup
    {
        Uid = Guid.NewGuid(),
        Steps = new List&#x3C;WizardStepSetup>
        {
            new DynamicWizardStepSetup
            {
                Uid = Guid.NewGuid(),
                Headline = "Step A",
                Description = "Select base product",
                Properties = new List&#x3C;WizardPropertySetup>
                {
                    new AttributeWizardPropertySetup
                    { 
                        Uid = Guid.NewGuid(),
<strong>                        PropertyUid = new Guid("30995d23-9492-4467-ab13-faa565afd579"),
</strong><strong>                        Mandatory = true
</strong><strong>                    },
</strong><strong>                    ...
</strong>                }
            },
            ...
        }
    },
    ...
}
</code></pre>

The wizard setup contains:

* A `Uid` for identification
* A list of `Steps` (`WizardStepSetup` instances)

Each step includes:

* A `Uid`, `Headline`, and `Description` to define the step
* A list of `Properties` of type `WizardPropertySetup`
  * They are inherited by `AttributeWizardPropertySetup`, which includes:
    * `Uid` — unique identifier for the wizard property
    * `PropertyUid` — references a property UID from the `SectionSetup` (can be found via API)
    * `Mandatory` — marks the field as required

### View and save permission

You can define **view** and **save** permissions on multiple levels within the product structure, including:

* Tabs
* Sections
* Individual Properties

These permissions ensure that only users with the correct access rights (fetched using the `/v1/permissions` endpoint) can view or modify specific UI components.

Here is an example of permission setup on a tab:

{% code title="C#" overflow="wrap" %}

```csharp

Tabs = new List<TabSetup>
{
    new DynamicTabSetup
    {
        Uid = Guid.NewGuid(),
        Label = "General",
        ViewPermission = new Guid("313e11e2-e2e4-4a82-82a0-f68ec8682522"),
        SavePermission = new Guid("e3d4c882-517c-4d89-9337-8a0b74d09b54"),
        Sections = new List<SectionSetup>
        {

            new DynamicSectionSetup
            {
```

{% endcode %}

Now, to view or save the tab, the user must have the required permission that has been set.

## Example of product structure with variants

In this example we will focus on adding variants as well as variant groups to our product structure.

To create a product structure that support **variants**, we must set `HasVariants = true` and provide a `VariantConfiguration` object. We do the same for `VariantGroupConfiguration.` Additionally, we define `VariationDefinitions`, which specify how variants are structured based on certain attributes like size, color, etc.

{% code title="C#" overflow="wrap" %}

```csharp
VariantConfiguration = new VariantConfiguration
{
    Tabs = new List<TabSetup>
    {
        new DynamicTabSetup
        {
            Uid = Guid.NewGuid(),
            Label = "VariantTab",
            Sections = new List<SectionSetup>
            {

                new DynamicSectionSetup
                {
                    Uid = Guid.NewGuid(),
                    Headline = "Variant Information",
                    Properties = new List<PropertySetup>
                    {
                        new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("de5572ed-1fb5-4192-a9ca-db73140f4cf5") },
                        new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("17c5eca3-a439-42b2-95df-8d4e82d1f16b") },
                        new AttributeSetup { Uid = Guid.NewGuid(), AttributeUid = new Guid("74a43fc6-63b1-4743-aa1e-816a8133b4c1") }
                    }
                },
                ...
            }
        },
        ...
    }
}

```

{% endcode %}

Above you can see we have set up `VariantConfiguration` just like `ProductConfiguration`. The main difference is that it does not contain `NameConfiguration`.

### Variant definitions

To support dynamic variant structures, we define one or more `VariationDefinitions`. Each defines how variants are differentiated based on selected attributes.

{% code title="C#" overflow="wrap" %}

```csharp
VariationDefinitions = new List<VariationDefinition>
{
    new VariationDefinition
    {
        Uid = Guid.NewGuid(),
        Name = "DemoNew",
        Alias = "DemoNew",
        NameConfiguration = new NameConfiguration
        {
            NamePattern = "{0}",
            NameAttributes = new List<Guid>
            {
                new Guid("17c5eca3-a439-42b2-95df-8d4e82d1f16b")
            }
        },
        DefiningAttributes = new List<Guid>
        {
            new Guid("17c5eca3-a439-42b2-95df-8d4e82d1f16b")
        },
        SortOrder = 0

    },
    ...
}
```

{% endcode %}

This example defines a single variation definition based on the Color attribute. The `NameConfiguration` ensures each variant’s name will be based on that attribute’s value.

### Always on defining attributes

Defining attributes are typically only available to variants if they are included in a specific `VariationDefinition`. However, there are cases where you may want certain attributes, like size, color, or SKU, to always be available for all variants, regardless of how the variations are defined.

The `AlwaysOnDefiningAttributes` property allows you to specify a set of defining attributes that are always included for every variant following the product structure.

In the example we have SKU as our `AlwaysOnDefiningAttributes`. If we want other options like name or StyleNumber, we would have to expand the `VariantDefinition` to contain those attributes before being able to assign them as an always show defining attribute.

{% code title="C#" overflow="wrap" %}

```csharp
AlwaysOnDefiningAttributes = new List<Guid>
{
    new Guid("17c5eca3-a439-42b2-95df-8d4e82d1f16b")
}
```

{% endcode %}

### Variant identifier definitions

When setting up the `VariantConfiguration` in the product structure, you also have the option to specify identifier definitions, just like you do for the product itself.

{% code title="C#" overflow="wrap" %}

```csharp
VariantIdentifierDefinitions = new List<IdentifierDefinition>
{
    new IdentifierDefinition
    {
        Uid = Guid.NewGuid(),
        Alias = "SKU",
        IdentifierPattern = "{0}",
        IdentifierAttributes = new List<Guid>
        {
            new Guid("17c5eca3-a439-42b2-95df-8d4e82d1f16b")
        }
    },
    ...
}
```

{% endcode %}

Below is a similar setup for variant groups, configured using the `VariantGroupConfiguration`. Variant groups help organize and manage variants that share common characteristics like color.

When looking at the `VariantGroupConfiguration` model below, you can see that it includes a property called `GroupingAttributes`. This property is a list of attribute GUIDs from the PIM, used to determine how variants are grouped. In this case, the attribute is color, meaning variants will be grouped by color.

{% code title="C#" overflow="wrap" %}

```csharp
VariantGroupConfiguration = new VariantGroupConfiguration
{
    GroupingAttributes = new List<Guid>
    {
        new Guid("c3fbf795-79be-4ab0-ae7d-e264b8227b88")
    },
    NameConfiguration = new NameConfiguration
    {
        NamePattern = "{0}",
        NameAttributes = new List<Guid>
        {
            new Guid("c3fbf795-79be-4ab0-ae7d-e264b8227b88")
        }
    },
    Tabs = new List<TabSetup?>
    {
        new DynamicTabSetup
        {
            Uid = Guid.NewGuid(),
            Label = "VariantGroupTab",
            Sections = new List<SectionSetup>
            {

                new DynamicSectionSetup
                {
                    Uid = Guid.NewGuid(),
                    Headline = "Variant Group Information",
                    Properties = new List<PropertySetup>
                    {
                        new AttributeSetup { AttributeUid = new Guid("c3fbf795-79be-4ab0-ae7d-e264b8227b88") },
                        new AttributeSetup { AttributeUid = new Guid("f0a0cc7b-1dbf-4b55-bb20-a2004400811c") }
                    }
                },
                ...
            }
        },
        ...
    }
}
```

{% endcode %}

### Variant group identifier definitions

Just like products and variants, `VariantGroupConfiguration` can also include identifier definitions. These definitions allow you to generate unique identifiers (e.g., group StyleNumbers or codes) for variant groups based on selected attributes.

{% code title="C#" overflow="wrap" %}

```csharp
VariantGroupIdentifierDefinitions = new List<IdentifierDefinition>
{
    new IdentifierDefinition
    {
        Uid = Guid.NewGuid(),
        Alias = "StyleNumber",
        IdentifierPattern = "{0}",
        IdentifierAttributes = new List<Guid>
        {
            new Guid("f0a0cc7b-1dbf-4b55-bb20-a2004400811c")
        }
    }
}
```

{% endcode %}

[^1]: {0} will render as your first nameAttribute, {1} as your second and so on. Alphanumeric characters are also allowed in the name pattern.
