Managing products
eClear allows you to define products that have the same identity across shops (global products) or whose identity is tied to a shop (local products). The difference is explained in more detail here. For most users global products are the right choice and that is why they are the focus of the following sections. If you manage local products just use the corresponding endpoints for local products.
Creating products
Products can be created in batches by POSTing to the products/globalendpoint. By default this method will raise an error if any product in the payload already exists. By setting the query parameter updateIfExists to true the method will instead update any existing products. The payload is a map where the keys are productIds.
{
"a-product-id": {
"productDetails": {
"languageAttributes": {
"de": {
"productName": "Eine deutscher Produktname",
"productDescription": "Eine deutsche Produktbeschreibung",
"productTags": ["Kategorie 1", "Kategorie 2"],
"merchantProductAttributes" : {
"a-field-that-I-declared-before": "ein-wert"
}
},
"en": {
"productName": "A German product name",
"productDescription": "A German product description",
"productTags": ["Category 1", "Category 2"],
"merchantProductAttributes" : {
"a-field-that-I-declared-before": "a-value"
}
}
},
"customsCodes": {
"taricCode": "9405499000",
"ukgtCode": "9405499000",
"taresCode": "94054900"
},
"productUids": {
"gtin": "4250549413076"
},
"merchantProductAttributes": {
"b-field-that-I-declared": "I am not language specific"
}
},
"shopIds": [44001331]
}
}languageAttributes are product attributes that can be expressed in different languages. All ISO 639 languages are allowed but the UI will only display German or English. merchantProductAttributes contain fields that you defined before because the standard fields of eClear are not sufficient to make a correct assignment and you want to provide more. As you can see merchantProductAttributes appears both in languageAttributes and in productDetailsdepending on how you declared the merchantProductAttributes. The fields productName, productDescription and productTags are particularly important for the DESCRIPTION auto-assignment strategy. German and English are used in the strategy but German works particularly well.
The customs codes in the customsCodes field are used for the auto-assignment strategy CUSTOMS-CODE. So if you have high quality customs codes provide them to save manual assignment effort. Making the request looks like:
POST https://eclear-solutions.com/api/vat-classification/v1/products/global HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}
{
"a-product-id": {
"productDetails": {
"languageAttributes": {
"de": {
"productName": "Eine deutscher Produktname",
"productDescription": "Eine deutsche Produktbeschreibung",
"productTags": ["Kategorie 1", "Kategorie 2"],
"merchantProductAttributes" : {
"a-field-that-I-decleared-before": "ein-wert"
}
},
"en": {
"productName": "A German product name",
"productDescription": "A German product description",
"productTags": ["Category 1", "Category 2"],
"merchantProductAttributes" : {
"a-field-that-I-decleared-before": "a-value"
}
}
},
"customsCodes": {
"taricCode": "9405499000",
"ukgtCode": "9405499000",
"taresCode": "94054900"
},
"productUids": {
"gtin": "4250549413076"
},
"merchantProductAttributes": {
"b-field-that-I-decleared": "I am not language specific"
}
},
"shopIds": [44001331]
}
}Product pictures
Once you have created products you can also upload product pictures. The following request uploads a picture for the product with id a-product-id:
POST https://eclear-solutions.com/api/vat-classification/v1/products/global/product-picture?productId=a-product-id HTTP/1.1
Content-Type: multipart/form-data; boundary=----BoundaryH4vDm8zJqR2tY6
Authorization: Bearer {{access_token}}
------BoundaryH4vDm8zJqR2tY6
Content-Disposition: form-data; name="file"; filename="a-nice-picture.png"
Content-Type: image/png
< ./a-nice-picture.png
------BoundaryH4vDm8zJqR2tY6--Reading products
Products can be searched by the following endpoint.
GET https://eclear-solutions.com/api/vat-classification/v1/products/global HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}This request will return a paged list. The maximum number of products on each page is governed by the size parameter. You can progress to the next or previous page by requesting the page in the links property. You can determine the detail of product attributes by passing the detail parameter. For example, the following query requests a page with the largest detail:
GET https://eclear-solutions.com/api/vat-classification/v1/products/global?detail=Large HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}A common action is to search products with specific productIds. The following request uses the productIds parameter to retrieve products with id a-product-id and test-123.
GET https://eclear-solutions.com/api/vat-classification/v1/products/global?productIds=a-product-id,test-123 HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}As in the example productIds can be a string of comma separated productIds or you can repeat the argument productIds to pass multiple values.
Use the query parameter filterCriteria to express more complex filtering. This parameter is an url encoded array of JSON objects. The JSON object has the following structure
{
"languageKey": "en", // ISO 639 language
"keywords": "mushroom", // search for this string in productName and productDescription
"productId": "my-id", // productId
"productName": "search-this-name", // productName must contain this string
"countryOfOrigin": "DE", // countryOfOrigin must match this ISO 3166-1 alpha-2 country
"productTag": "food", // productTag must contain food
"operation": "AND" // chain the next element by this logical operator
}The languageKey property needs only to be provided if productName or productTag is also provided. If you do not provide languageKey and provide keywords then the search
is over English language. The properties in the JSON object are composed with a logical AND. For example:
{
"languageKey": "de",
"productTag": "tag",
"productName": "tas"
}filters products that have productTags that contain "tag" and that have a productName that contains "tas".
The following request
GET https://eclear-solutions.com/api/vat-classification/v1/products/global?filterCriteria=%5B%7B%22productId%22%3A%20%22a-product-id%22%2C%20%22operation%22%3A%20%22OR%22%7D%2C%20%7B%22languageKey%22%3A%20%22de%22%2C%20%22productName%22%3A%20%22Tast%22%7D%5D HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}filters products that have a productId that contains "a-product-id" or that have a German productName that contains "Tast". The query parameter filterCriteria has the following form before URL encoding:
[
{
"productId": "a-product-id",
"operation": "OR"
},
{
"languageKey": "de",
"productName": "Tast"
}
]Short search values can result in long search times. For example productName=t would search over all products that have product names that contain a "t". If the search takes too long you might receive 503 HTTP status codes. The remedy against this behaviour is to specify your search term further.
As you can see from the examples the search partially matches the provided values to the field values. For example:
[
{
"productName": "app",
"languageKey": "en"
}
]matches a product with productName apple juice. Some search values that you provide have special meaning as explained in the following table:
| Expression | Meaning | Example |
|---|---|---|
(space) | A space between two or more values is interpreted as an AND | apple juice matches products that contain both "apple" and "juice" in any order |
or | "or" enclosed in spaces is interpreted as an OR | apple or juice matches products that contain "apple" or "juice" |
- | A space followed by a dash in front of a value negates it | apple -juice matches products that contain "apple" and not "juice" |
\"phrase\" | A phrase between escaped quotes expresses that search values must be words apart. Each space between search values expresses a placeholder word. | \"apple juice\" matches products that contain apple followed by juice. \"apple juice\" matches products that contain apple followed by an arbitrary word and then apple |
To give an example for searching productName for values that are one word apart consider the following filterCriteria search query before URL encoding:
[
{
"languageKey": "de",
"productName": "\"Apple Juice\""
}
]This search will match Apple Mango Juice but not Apple Juice.
Updating products
Products can be updated partially or entirely through PATCH and PUT methods, respectively. Updating partially means that only the product attributes in the payload are changed server side. All other product attributes stay as they are:
PATCH https://eclear-solutions.com/api/vat-classification/v1/products/global?productId=test444¤tVersion=1 HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}
{
"productDetails": {
"languageAttributes": {
"de": {
"productTags": ["A tag"]
}
}
}
}This request partially updates the product attribute productTags. All other product attributes keep their values. Note that on top of providing the productId in the query parameter, you also have to provide the currentVersion of the product. This mechanism guards against race conditions that would entail if multiple product updates happen at the same time. So the flow to update a product is to get its currentVersion first and then do the update.
A replacement or entire update happens through the following request:
PUT https://eclear-solutions.com/api/vat-classification/v1/products/global?productId=test333¤tVersion=1 HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{access_token}}
{
"productDetails": {
"languageAttributes": {
"de": {
"productTags": ["A tag only"]
}
}
}
}After the update the product's only product attributes are productTags in German and the productId.
Product pictures
Product pictures can be replaced with the following request:
PUT https://eclear-solutions.com/api/vat-classification/v1/products/global/product-picture?productId=a-product-id HTTP/1.1
Content-Type: multipart/form-data; boundary=----BoundaryH4vDm8zJqR2tY6
Authorization: Bearer {{access_token}}
------BoundaryH4vDm8zJqR2tY6
Content-Disposition: form-data; name="file"; filename="a-different-picture.png"
Content-Type: image/png
< ./a-different-picture.png
------BoundaryH4vDm8zJqR2tY6--Here the existing picture for the product with id a-product-id is replaced with a picture that has file name a-different-picture.png.