Use of Product endpoints

How to use product endpoints in API

Creating a product

POST /v1/products

When creating new products, we can add more information in regards to their product structure, variation definition, classifications, workflow state and business units. You are not required to include all of these in the product setup. However, in this example we will set everything up so that you can get an idea of how to do your specific task.

Fetching the product structure and variation definition

C#
ProductStructure clothingProductStructure = _apiClient.ProductStructures.GetProductStructures().Single(x => x.Alias == "Clothing");

The GetProductStructures method sends an HTTP request to the /v1/productstructures endpoint. It returns a list of ProductStructure. We use Single to select the only product structure with the alias "Clothing".

Alternatively, you can use the /v1/productstructures/{uid} endpoint if you know the specific UID of the product structure you would like to use.

Within the ProductStructure instance, you can now get the VariationDefinition.

C#
VariationDefinition clothingVariation = clothingProductStructure.VariationDefinitions.Single(x => x.Name == "Clothing");

We are now able to set the product structure and variation definition Uid on our product model.

C#
CreateProductModel<ProductModel> productModelToBeCreated = new()
{
   ProductStructureUid = clothingProductStructure.Uid,
   VariationDefinitionUid = clothingVariation.Uid,
};

Adding classifications

After defining the product structure and its variations, you can improve it by adding classifications.

Classifications help organize products into groups, making it easier to manage and find product information. Each product can have multiple classifications, but only one can be the primary. This primary classification highlights the most important category for the product.

C#
CreateProductModel<ClothingProductModel> productModelToBeCreated = new()
{
    ProductStructureUid = clothingProductStructure.Uid,
    VariationDefinitionUid = clothingVariation.Uid,

    Classifications = new List<SetClassificationModel>
    {
        new SetClassificationModel()
        {
            CategoryId = 242,
            IsPrimary = true,
            OwnerReference = "made by demo api",
            SortOrder = 0
        },
        new SetClassificationModel()
        {
            CategoryId = 240,
            IsPrimary = false,
            OwnerReference = "made by demo api",
            SortOrder = 0
        },
        new SetClassificationModel()
        {
            CategoryId = 241,
            IsPrimary = false,
            OwnerReference = "made by demo api",
            SortOrder = 0
        }
    },

Adding values

After setting up the clasiffications you now only need to set the values the product should be created with. Using the Struct Pim Model generator, we have generated some C# classes in order to have strongly typed models that matches the models in Struct PIM.

With those we can now specify what type of values we want. In this case we are working with clothing as seen in the code above so we would also want the values to be of type ClothingProductModel.

C#
CreateProductModel<ClothingProductModel> productModelToBeCreated = new()
{
    ProductStructureUid = clothingProductStructure.Uid,
    VariationDefinitionUid = clothingVariation.Uid,

    Classifications = new List<SetClassificationModel>
    {
        new SetClassificationModel()
        {
            CategoryId = 242,
            IsPrimary = true,
            OwnerReference = "made by demo api",
            SortOrder = 0
        },
        new SetClassificationModel()
        {
            CategoryId = 240,
            IsPrimary = false,
            OwnerReference = "made by demo api",
            SortOrder = 0
        },
        new SetClassificationModel()
        {
            CategoryId = 241,
            IsPrimary = false,
            OwnerReference = "made by demo api",
            SortOrder = 0
        }
    },

    Values = new ClothingProductModel
    {
        Name = new List<LocalizedData<string>>
        {
            new LocalizedData<string> { CultureCode = "en-GB", Data = "New Awesome         Gadget" },
            new LocalizedData<string> { CultureCode = "da-DK", Data = "Ny Fantastisk Gadget" }
        },
        
    }
};

You can incorporate various attributes under values, such as Name, to identify the product. The Name attribute is of type LocalizedData<string>, allowing the name to vary by language in the PIM. This is done by specifying the CultureCode and Data for the Name attribute.

Now we are mostly done. The remaining information that can be defined besides different values are businessunits that the product has relation to, and the workflow it is assigned to.

C#
 CreateProductModel<ClothingProductModel> productModelToBeCreated = new()
 {
     ProductStructureUid = clothingProductStructure.Uid,
     VariationDefinitionUid = clothingVariation.Uid,
     
     WorkflowStateUid = null,

In the example above we set the WorkflowStateUid as null, since we do not have a workflow for.

When adding business units to the product we must first retrieve the business unit. We do this through the /v1/businessunits endpoint. Just like previously with product we select the business unit through its alias "ClothingUnit".

C#
 BusinessUnitModel clothingBusinessUnit = _apiClient.BusinessUnits.GetBusinessUnits().Single(x => x.Alias == "ClothingUnit");

Once we have the business unit we can proceed to add it to the product being created.

C#
CreateProductModel<ClothingProductModel> productModelToBeCreated = new()
{
    ProductStructureUid = clothingProductStructure.Uid,
    VariationDefinitionUid = clothingVariation.Uid,
    
    WorkflowStateUid = null,

    BusinessUnits = new List<BusinessUnitRelationModel>
    {
        new BusinessUnitRelationModel
        {
            BusinessUnitUid = clothingBusinessUnit.Uid,
        },
    },

With everything now set up we can conclude the example by adding the product to the PIM throught the use of the /v1/products enpoint.

C#
_apiClient.Products.CreateProduct(productModelToBeCreated);

Using the /search endpoint

POST /v1/products/search

When using the search endpoint to find product IDs, the process can seem complex initially, especially when multiple conditions are involved, as shown in the example above.

In the following example we will demystify the request body and set an example to give a better idea on how to perform this specific task.

C#
SearchModel search = new SearchModel();
                    

Before we can use the search endpoint we need to first understand how to use the SearchModel and set up conditions.

We start by instantiating the SearchModel publicating it with information. We begin with the IncludeArchived property which is a boolean we can set to true or false dependent on if you want to include archived items in result.

C#
SearchModel search = new SearchModel()
{                    
    IncludeArchived = false,
    QueryModel = new BooleanQueryModel
    {
                    

Once this is done we begin setting up the abstract QueryModel which can either be of type SimpleQueryModel or BooleanQueryModel.

  • SimpleQueryModel: Simple query model used for querying specific fields. Used for specifying fields to filter search by.

  • BooleanQueryModel: Query wrapper for sub queries where the BooleanOperator operates between the sub queries. Allows for nested queries.

In the example above we want to set up multiple search conditions. For that we would need SubQueries which only BooleanQueryModel can contain. However, before adding them we need to specify with a BooleanOperator if at least one or all conditions in the SubQueries must match by asigning the boolean the value 1 or 0. By selecting the BooleanOperator.And (0), we have choosen that all conditions must match for the search to pick up the product id.

C#
SearchModel search = new SearchModel()
{                    
    IncludeArchived = false,
    QueryModel = new BooleanQueryModel
    {
        BooleanOperator = BooleanOperator.And,
        SubQueries = new List<QueryModel>
        {
            new SimpleQueryModel
            {
                Filters = new List<FieldFilterModel>
                {
                    new FieldFilterModel { }
                    

The SubQueries contain a list of SimpleQueryModels that each can contain a list of FieldFilterModels where the conditions for the search are written. In the scenario where a SimpleQueryModel contains multiple FieldFilterModels, it is adviced to add a BooleanOperator in order to specify if all or only one condition must match.

C#
SearchModel search = new SearchModel()
{                    
    IncludeArchived = false,
    QueryModel = new BooleanQueryModel
    {
        BooleanOperator = BooleanOperator.And,
        SubQueries = new List<QueryModel>
        {
            new SimpleQueryModel
            {
                Filters = new List<FieldFilterModel>
                {
                    new FieldFilterModel
                    {
                        FieldUid = "",
                        QueryOperator = QueryOperator.Equals,
                        FilterValue = ""
                    }
                    

The FieldFilterModel contains three properties, as seen in the example above.

  • FieldUid: Uid of field to query.

  • QueryOperator: Can be any of:

    • Equals / 0 (Value must start with FilterValue)

    • WildcardEquals / 1 (Value must be smaller than FilterValue)

    • SmallerThan / 2 (Value must be smaller than FilterValue)

    • LargerThan / 3 (Value must be larger than FilterValue)

    • IsEmpty / 4 (Value must be empty)

    • IsNotEmpty / 5 (Value must not be empty)

    • Contains / 6 (Value must contain FilterValue)

      • NotContains / 7 (Value must not contain FilterValue)

    • NotEquals / 8 (Value must not be exactly equal to FilterValue (not considering casing))

    • NotWildcardEquals / 9 (Value must not start with FilterValue)

    • InList / 10 (Item field value must match any of the in provided values in FilterList)

  • FilterValue: Value to filter for using the QueryOperator. When QueryOperator is "InList", FilterValue must be an array of values to query for.'

A good way to get all queryable fields from the PIM is through the endpoint /v1/products/queryablefields.

With this you can set up simple or complex SearchModels using the /v1/products/search endpoint.

Example of searching for products

The following example demonstrate a query that looks for products with "Adidas" as the brand, "Portugal" as the country of origin, and having at least 15 variants.

C#
SearchModel searchModel = new SearchModel()
{
    IncludeArchived = false,
    QueryModel = new BooleanQueryModel()
    {
        BooleanOperator = BooleanOperator.And,
        SubQueries = new()
        {
            new SimpleQueryModel()
            {
                BooleanOperator = BooleanOperator.And,
                Filters = new List<FieldFilterModel>()
                {
                    // Country of origin
                    new FieldFilterModel()
                    {
                        FieldUid = "e2342c65-3def-4f57-9fe7-3fe9d3f093ed_en-GB_NA",
                        QueryOperator = QueryOperator.Equals,
                        FilterValue = "Portugal"
                    },

                    // Brand
                    new FieldFilterModel()
                    {
                        FieldUid = "f886acd6-1397-4004-aba0-a3b2d6180151_NA_NA",
                        QueryOperator = QueryOperator.Equals,
                        FilterValue = "Adidas"
                    }
                }
            },

            new SimpleQueryModel()
            {
                Filters = new()
                {
                    // Number of variants
                    new FieldFilterModel()
                    {
                        FieldUid = "PIM_VariantsCount",
                        QueryOperator = QueryOperator.LargerThan,
                        FilterValue = "14"
                    }
                }
            }
        }
    }
};

List<int> queryResult = _apiClient.Products.Search(searchModel);

Last updated