In the previous articles of this serie, we have seen how to script the creation of Catalog and Category items in XC. Now we are taking a step further in the complexity and we’ll create a Sellable Item, with some properties.
A SellableItem may have its own properties. You can use Composer Templates or Entity Components to create and use the item’s properties. Here is a good article that describe the difference between those two approaches.
In our case, we want to use Composer Templates, because it permits us to use the same type of API call to xConnect in order to create a Composer Template and to fill those properties inside a Sellable Item.
Creating a Composer Template
First of all, let’s create a Composer Template. Image you’ll have items representing cars. We will need information about the type of cars, the fuel, the gearbox, etc…
As usual, let’s create a Composer Template in Business Tools, saving each call to the xConnect API with Chrome’s Dev Tools.

Creating a template is straightforward, we have a POST request to /api/DoAction() where we post a JSON string with the meta information of the template.
Here is the resulting Powershell script:
Function AddTemplate {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[string] $Version,
[string] $Name
)
$itemId = "Entity-ComposerTemplate-$Name"
$body = @{entityView=@{Name="CreateTemplate";DisplayName="Create Template";EntityId="";Action="CreateTemplate";ItemId=$itemId;EntityVersion=1;VersionedItemId="Entity-ComposerTemplate-$name-1";Properties=@( `
[pscustomobject]@{Name="Version";DisplayName="Version";Value=$Version;IsHidden=$True;OriginalType="System.Int32";IsReadOnly=$True;IsRequired=$True},`
[pscustomobject]@{Name="Name";DisplayName="Name";Value="$Name";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="DisplayName";DisplayName="Display Name";Value="$Name";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False},`
[pscustomobject]@{Name="ViewName";DisplayName="View Name";Value="$Name";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="ViewDisplayName";DisplayName="View Display Name";Value="$Name";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False}`
);DisplayRank=500;UiHint="Flat";Icon="dashboard"}} | ConvertTo-Json -Depth 100
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/DoAction()"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
if ($Res.ResponseCode -ne "Ok") {
Write-Host($uri)
Write-Host($body)
Write-Host($Res)
return $Res.Messages[0]
}
return $Res.ResponseCode
}
A template is a list of properties (lite Gearbox, Fuel or CarType). Let’s create some properties in Business Tools and see the resulting call to xConnect API.

In the JSON sent by Business Tools to xConnect, we note a new field, called ItemId, with a value unknown to us: Composer-xxxxx
If we create a script as usual and let this value be empty, the property will be created, but not persisted in the template. So we need to get the value of this ItemId.
Thankfully, there are not so many places to search where to get this value. We can see that before the call to DoAction(), our browser has called a GetEntityView(). In xConnect’s answer to this call, we do find the exact value we are looking for. Yeah !


The script to find this ItemId value is easy to write:
Function GetItemComposer {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Name,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri
)
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/GetEntityView()"
$body = @{entityId="Entity-ComposerTemplate-$Name"; forAction=""; itemId=""; viewName="Master"} | ConvertTo-Json -Depth 100
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$catVersion = ($Res.ChildViews[1]).ItemId
if ($null -eq $catVersion) {
return 0
}
return $catVersion
}
And adding a property to the template, with this ItemId is now possible to script
Function AddTemplateProperty {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[string] $Name,
[string] $PropertyName,
[string] $PropertyDisplayName,
[string] $PropertyType,
[string] $ItemId
)
$entityId = "Entity-ComposerTemplate-$Name"
$versionTemplate = GetTemplateVersion -Token $token -TemplateName $Name -IdentityServiceUri $IdentityServiceUri
$body = @{entityView=@{Name="AddProperty";DisplayName="Add Property";EntityId="Entity-ComposerTemplate-$Name";Action="AddProperty";ItemId="$ItemId";EntityVersion=1;VersionedItemId="$ItemId-1";Properties=@( `
[pscustomobject]@{Name="Version";DisplayName="Version";Value="$versionTemplate";IsHidden=$True;OriginalType="System.Int32";IsReadOnly=$True;IsRequired=$True},`
[pscustomobject]@{Name="Name";DisplayName="Name";Value="$PropertyName";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="DisplayName";DisplayName="Display Name";Value="$PropertyDisplayName";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False},`
[pscustomobject]@{Name="PropertyType";DisplayName="Property Type";Value="$PropertyType";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True}`
);DisplayRank=500;UiHint="Flat";Icon="dashboard"}} | ConvertTo-Json -Depth 100
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/DoAction()"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
if ($Res.ResponseCode -ne "Ok") {
Write-Host($uri)
Write-Host($body)
Write-Host($Res)
return $Res.Messages[0]
}
return $Res.ResponseCode
}
A Composer template uses tags to know which sellable item it has to be applied to. Adding a tag to this template can be done with the following script
Function ManageTemplateTags {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[string] $Name,
[string] $Tag
)
$entityId = "Entity-ComposerTemplate-$Name"
$versionTemplate = GetTemplateVersion -Token $token -TemplateName $Name -IdentityServiceUri $IdentityServiceUri
$body = @{entityView=@{Name="ManageTemplateTags";DisplayName="Manage Tags";EntityId=$entityId;Action="ManageTemplateTags";EntityVersion=1;VersionedItemId="-1";Properties=@( `
[pscustomobject]@{Name="Version";DisplayName="Version";Value="$versionTemplate";IsHidden=$True;OriginalType="System.Int32";IsReadOnly=$True;IsRequired=$True},`
[pscustomobject]@{Name="Tags";DisplayName="Tags";Value="['$Tag']";IsHidden=$False;OriginalType="List";IsReadOnly=$False;IsRequired=$True}`
);DisplayRank=500;UiHint="Flat";Icon="dashboard"}} | ConvertTo-Json -Depth 100
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/DoAction()"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
if ($Res.ResponseCode -ne "Ok") {
Write-Host($uri)
Write-Host($body)
Write-Host($Res)
Write-Host($Res.Messages)
return $Res.Messages[0]
}
return $Res.ResponseCode
}
As we did before, we can also check the version number of the template, to see if the template already exists before creating it
Function GetTemplateVersion {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$TemplateName,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri
)
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/ComposerTemplates"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Get -Headers $headers
$catVersion = ($Res.value | Where-Object { $_.FriendlyId -eq $TemplateName} | Select-Object Version)
if ($null -eq $catVersion -or $catVersion.Count -eq 0) {
return 0
}
return $catVersion[0].Version
}
Now we can group all those scripts together to create our template
Function CreateTemplate {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[pscustomobject] $Data
)
$name = $Data.Name
$catalog = $Data.Catalog
$tag = $Data.Tag
$template_friendlyId = "$catalog-$name"
$catalogEntity = "Entity-Catalog-$catalog"
$version = GetTemplateVersion -Token $token -TemplateName $name -IdentityServiceUri $IdentityServiceUri
if ($version -eq 0) {
$result = AddTemplate -Token $token -Version $version -Name $name -IdentityServiceUri $IdentityServiceUri
if ($result -ne "Ok") {
Write-Host("Error creating template $name : $result")
Exit 1
}
Write-Host("Created template $name")
$result = ManageTemplateTags -Token $token -Name $name -Tag $tag -IdentityServiceUri $IdentityServiceUri
$itemComposerId = GetItemComposer -Token $token -Name $name -IdentityServiceUri $IdentityServiceUri
$result = AddTemplateProperty -Token $token -ItemId $itemComposerId -Name $name -PropertyName "GearBox" -PropertyDisplayName "GearBox" -PropertyType "System.String" -IdentityServiceUri $IdentityServiceUri
$result = AddTemplateProperty -Token $token -ItemId $itemComposerId -Name $name -PropertyName "Fuel" -PropertyDisplayName "Fuel" -PropertyType "System.String" -IdentityServiceUri $IdentityServiceUri
$result = AddTemplateProperty -Token $token -ItemId $itemComposerId -Name $name -PropertyName "CarType" -PropertyDisplayName "CarType" -PropertyType "System.String" -IdentityServiceUri $IdentityServiceUri
} else {
Write-Host("Already existing template $name")
}
}
The call to this function is
CreateTemplate -Token $token -Data @{Catalog=$catalog; Name=$templateName; Tag="car"} -IdentityServiceUri "https://$authoringAlias"
Creating a Sellable Item
Adding a sellable item is now easy using the same technique as usual. The resulting script is as follow
Function AddSellableItem {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[string] $Category,
[string] $Version,
[string] $ProductId,
[string] $Name,
[string] $DisplayName,
[string] $Description,
[string] $Brand,
[string] $Manufacturer,
[string] $TypeOfGood,
[string] $Tags
)
$body = @{entityView=@{Name="Details";DisplayName="Details";EntityId=$Category;Action="AddSellableItem";ItemId="";Properties=@( `
[pscustomobject]@{Name="Version";DisplayName="Version";Value=$Version;IsHidden=$True;OriginalType="System.Int32";IsReadOnly=$True;IsRequired=$True},`
[pscustomobject]@{Name="ProductId";DisplayName="Product Id";Value=$ProductId;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="Name";DisplayName="Name";Value=$Name;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="DisplayName";DisplayName="Display Name";Value=$DisplayName;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="Description";DisplayName="Description";Value=$Description;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False},`
[pscustomobject]@{Name="Brand";DisplayName="Brand";Value=$Brand;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False},`
[pscustomobject]@{Name="Manufacturer";DisplayName="Manufacturer";Value=$Manufacturer;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False},`
[pscustomobject]@{Name="TypeOfGood";DisplayName="TypeOfGood";Value=$TypeOfGood;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$False},`
[pscustomobject]@{Name="Tags";DisplayName="Tags";Value=$Tags;IsHidden=$False;OriginalType="List";IsReadOnly=$False;IsRequired=$False;UiType="Tags"}`
);DisplayRank=500;UiHint="Flat";Icon="dashboard"}} | ConvertTo-Json -Depth 100
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/DoAction()"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
if ($Res.ResponseCode -ne "Ok") {
Write-Host($body)
Write-Host($Res)
Write-Host($Res.Messages)
}
return $Res.ResponseCode
}
When the sellable item is done, we need to add its properties we created in the Composer Template. Doing that in Business Tools, we can see we need here also a ItemId in order to persist the information we send to this sellable item. The script to get this SellableItemComposer is
Function GetSellableItemComposer {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Name,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri
)
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/GetEntityView()"
$body = @{entityId="Entity-SellableItem-$Name"; forAction=""; itemId=""; viewName="Master"} | ConvertTo-Json -Depth 100
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$catVersion = ($Res.ChildViews[0]).ItemId
if ($null -eq $catVersion) {
return 0
}
return $catVersion
}
We also need to know which version of the sellable item we need to work with.
Function GetSellableItemEntityVersion {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$SellableItem,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri
)
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/GetEntityView()"
$body = @{entityId="Entity-SellableItem-$SellableItem"; forAction=""; itemId=""; viewName="Master"} | ConvertTo-Json -Depth 100
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$EntityVersion = ($Res.Properties | Where-Object { $_.Name -eq "EntityVersion"} | Select-Object Value)
if ($null -eq $EntityVersion -or $EntityVersion.Count -eq 0) {
return 0
}
return $EntityVersion.Value
}
Here is the script to save the properties from this sellable item’s composer template
Function EditView {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[string] $Name,
[string] $SellableItem,
[string] $Version,
[string] $CarType,
[string] $Gearbox,
[string] $Fuel
)
$composerId = GetSellableItemComposer -Token $token -Name $name -IdentityServiceUri $IdentityServiceUri
$EntityId = "Entity-SellableItem-$SellableItem"
$EntityVersion = GetSellableItemEntityVersion -Token $Token -IdentityServiceUri $IdentityServiceUri -SellableItem "$SellableItem"
$body = @{entityView=@{Name="EditView";DisplayName="Edit View";EntityId=$EntityId;Action="EditView";EntityVersion=$EntityVersion;ItemId=$composerId;VersionedItemId="$composerId-1";Properties=@( `
[pscustomobject]@{Name="Version";DisplayName="Version";Value=$Version;IsHidden=$True;OriginalType="System.Int32";IsReadOnly=$True;IsRequired=$True},`
[pscustomobject]@{Name="CarType";DisplayName="CarType";Value=$CarType;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="Fuel";DisplayName="Fuel";Value=$Fuel;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="Gearbox";DisplayName="Gearbox";Value=$Gearbox;IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
);DisplayRank=500;UiHint="Flat";Icon="dashboard"}} | ConvertTo-Json -Depth 100
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/DoAction()"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
if ($Res.ResponseCode -ne "Ok") {
Write-Host($uri)
Write-Host($body)
Write-Host($Res)
return $Res.Messages[0]
}
return $Res.ResponseCode
}
Adding price to this sellable item is also straightforward with this technique. Don’t forget to have the correct versiom of the sellable item !
Function AddPriceToSellableItem {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[string] $SellableItem,
[string] $Version,
[int] $Price
)
$entityId = "Entity-SellableItem-$SellableItem"
$EntityVersion = GetSellableItemEntityVersion -Token $Token -IdentityServiceUri $IdentityServiceUri -SellableItem "$SellableItem"
$body = @{entityView=@{Name="SellableItemListPricing";DisplayName="List Pricing";EntityId=$entityId;Action="AddSellableItemListPrice";ItemId="";EntityVersion=$EntityVersion;VersionedItemId="-1";Properties=@( `
[pscustomobject]@{Name="Version";DisplayName="Version";Value=$Version;IsHidden=$True;OriginalType="System.Int32";IsReadOnly=$True;IsRequired=$True},`
[pscustomobject]@{Name="Currency";DisplayName="Currency";Value="SEK";IsHidden=$False;OriginalType="System.String";IsReadOnly=$False;IsRequired=$True},`
[pscustomobject]@{Name="ListPrice";DisplayName="List Price";Value="$Price";IsHidden=$False;OriginalType="System.Decimal";IsReadOnly=$False;IsRequired=$True}`
);DisplayRank=500;UiHint="Flat";Icon="dashboard"}} | ConvertTo-Json -Depth 100
$contentType = 'application/json'
$headers = BuildHeaders($token)
$uri = "$IdentityServiceUri/api/DoAction()"
$Res = Invoke-RestMethod -Uri $uri -ContentType $contentType -Method Post -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
if ($Res.ResponseCode -ne "Ok") {
Write-Host($uri)
Write-Host($body)
Write-Host($Res)
return $Res.Messages[0]
}
return $Res.ResponseCode
}
We wrap all those functions in one neat function to create our sellable item
Function CreateSellableItemCar {
[CmdletBinding()]
PARAM
(
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$Token,
[string][parameter(Mandatory = $true)][ValidateNotNullOrEmpty()]$IdentityServiceUri,
[pscustomobject] $Data
)
$catalog = $Data.Catalog
$category = $Data.Parent
$sellableItem = $Data.ProductId
$siName = $Data.Name
$siDisplayName = $Data.DisplayName
$siDescription = $Data.Description
$brand = $Data.Brand
$manufacturer = $Data.Manufacturer
$tags = $Data.Tags
$price = $Data.Price
$info = $Data.Info
$category_friendlyId = "$catalog-$category"
$sellableItemEntity = "Entity-Category-$catalog-$category"
$version = GetCategoryVersion -Token $token -Category $category_friendlyId -IdentityServiceUri $IdentityServiceUri
$versionSellableItem = GetSellableItemInfoVersion -Token $token -SellableItem $sellableItem -IdentityServiceUri $IdentityServiceUri
if ($versionSellableItem -eq 0) {
$result = AddSellableItem -Token $token -Category $sellableItemEntity -Version $version -ProductId $sellableItem -Name $siName -DisplayName $siDisplayName -Description $siDescription -Brand $brand -Manufacturer $manufacturer -Tags $tags -IdentityServiceUri $IdentityServiceUri
if ($result -ne "Ok") {
Write-Host("Error adding sellable item $sellableItem : $result")
Exit 1
}
Write-Host("Added Sellable item $sellableItem")
$versionSellableItem = GetSellableItemInfoVersion -Token $token -SellableItem $sellableItem -IdentityServiceUri $IdentityServiceUri
$Data.Info | ForEach-Object -Process {
$carType = $_.CarType
$fuel= $_.Fuel
$gearbox= $_.Gearbox
$result = EditView -Token $token -Name $sellableItem -SellableItem "$sellableItem" -Version $versionSellableItem -IdentityServiceUri $IdentityServiceUri -CarType $carType -Fuel $fuel -Gearbox $gearbox
if ($result -ne "Ok") {
Write-Host("Error adding info : $result")
Exit 1
}
Write-Host("Added Properties for Sellable item $sellableItem")
$versionSellableItem = GetSellableItemInfoVersion -Token $token -SellableItem $sellableItem -IdentityServiceUri $IdentityServiceUri
$result = AddPriceToSellableItem -Token $token -SellableItem "$sellableItem" -Version $versionSellableItem -Price $price -IdentityServiceUri $IdentityServiceUri
if ($result -ne "Ok") {
Write-Host("Error adding price $name : $result")
Exit 1
}
Write-Host("Added Price for Sellable item $sellableItem")
$versionSellableItem = GetSellableItemInfoVersion -Token $token -SellableItem $sellableItem -IdentityServiceUri $IdentityServiceUri
}
Write-Host("Created sellable item $sellableItem")
}else {
Write-Host("Already existing sellable item $sellableItem")
}
}
Calling this function :
CreateSellableItemCar -Token $token -IdentityServiceUri "https://$authoringAlias" -Data @{Catalog=$catalog; Parent=$category1; ProductId="CAR1"; Name="Ferrari"; DisplayName="Ferrari"; Description="A nice red car"; Brand="Ferrari"; Manufacturer="Ferrari"; Tags="['bil']"; Price=1000000; Info=@([pscustomobject]@{CarType="SUV"; Fuel="Gas";Gearbox="Manual"})}
This was a long article with plenty of scripts. In the next article, which will be the last one of this serie, I’ll show you how to add an inventary to an item, and to programatically approve this item.