Manage product and stock information
Products API allows suppliers to manage their products.
As a supplier you can create products and publish them to retailers. Manage price and stock information. Product creation and updates can be done either one by one or in batches.
As a retailer you can get product information that suppliers have published to you with stock and price information.
Environment | Protocol | Host |
---|---|---|
Test | HTTPS | argon.ecom-api.posti.com |
Prod | HTTPS | ecom-api.posti.com |
As with other requests to the system, user must be authenticated as described in Posti Authentication API.
Older V2 documentation can be found here.
Supplier can create and manage products. Product lifecycle from suppliers point of view:
Note that API returns max 2000 objects per request. Where there is page object present in response you need to check
the totalElements
and totalPages
number. And loop through the pages if needed with
providing
&page=0 or &page=1 etc
as a parameter. First page is 0.
"page": { "size": 2000, "totalElements": 3322, "totalPages": 2, "number": 0 }
Same endpoint PUT /ecommerce/v3/inventory can be used to create and update product data. Note that creation of a product does not make it visible to retailers. They need to be published separately.
externalId
must be unique inside of a supplier. This is a key field that is used to handle stock
allocations and
make updates to product data and stock/price information.
Important: You can use only numbers, letters, dashes “-” and dots “.” in externalId.
It’s not allowed to use:
Product data has two sections:
PUT {{glueApiUrl}}/v3/inventory
[ { "product": { "externalId": "Example-product-01", "eanCode": "1234567890005", "recommendedRetailPrice": 12, "vatPercentage": 20, "measurements": { "weight": 1.43, "length": 0.2, "width": 0.065, "height": 0.45, "volume": 0.515 }, "unitOfMeasure": "KPL", "descriptions": { "fi": { "name": "Fishing boots", "shortDescription": "Green fishing boots", "description": "Longer description for these good fishing boots" } } } } ]
[ { "product": { "externalId": "Example-product-02", "eanCode": "1234567891005", "recommendedRetailPrice": 12, "vatPercentage": 20, "measurements": { "weight": 1.43, "length": 0.2, "width": 0.065, "height": 0.45, "volume": 0.515 }, "unitOfMeasure": "KPL", "isFragile": false, "categories": { "en": [ "Shoes" ], "fi": [ "Kengät" ] }, "isDangerousGoods": true, "hasBestBeforeDate": true, "warrantExpiration": 240, "hasWarranty": false, "warrantSerialControlled": false, "descriptions": { "en": { "name": "Fishing boots", "shortDescription": "Green fishing boots", "description": "Longer description for these good fishing boots", "supplier": "Nokia", "attachments": [ { "name": "Picture 1", "type": "marketing", "contentType": "jpg", "uri": "https://ae01.alicdn.com/kf/Hcdd71b50fe274a299edbfcf4755fa8d9m/Outdoor-Long-Waterproof-Fishing-Boots-Breathable-Fishing-Waders-Boot-Soft-and-comfortable-Fishing-Wading-Shoes-Rubber.jpg_Q90.jpg_.webp" } ], "comments": [ { "type": "Instructions", "name": "Maintenance", "value": "Wash with fresh water after usage." } ], "specifications": [ { "type": "Tehnical data", "properties": [ { "name": "Operating voltage", "value": "220", "specifier": "V", "description": "Description if needed" }, { "name": "Colour", "value": "White" } ] }, { "type": "Measures", "properties": [ { "name": "Waist", "value": "94", "specifier": "cm" }, { "name": "Size", "value": "M", "specifier": "EU" } ] } ] }, "fi": { "name": "Saappaat", "shortDescription": "Vihreät saappaat", "description": "Pidempi kuvaus näistä hyvistä kalasaappaista", "supplier": "Nokia", "attachments": [ { "name": "Picture 1", "type": "marketing", "contentType": "jpg", "uri": "https://ae01.alicdn.com/kf/Hcdd71b50fe274a299edbfcf4755fa8d9m/Outdoor-Long-Waterproof-Fishing-Boots-Breathable-Fishing-Waders-Boot-Soft-and-comfortable-Fishing-Wading-Shoes-Rubber.jpg_Q90.jpg_.webp" } ], "comments": [ { "type": "Ohjeet", "name": "Huolto", "value": "Pese puhtaalla vedellä käytön jälkeen." } ], "specifications": [ { "type": "Tehnical data", "properties": [ { "name": "Operating voltage", "value": "220", "specifier": "V", "description": "Description if needed" }, { "name": "Colour", "value": "White" } ] }, { "type": "Measures", "properties": [ { "name": "Waist", "value": "94", "specifier": "cm" }, { "name": "Size", "value": "M", "specifier": "EU" } ] } ] } } } } ]
Find full schema description here.
For changing / updating product description etc. the same request can be used that was used to create the product.
After products have been created they need to be published to retailer's product catalogs. The catalog is like retailer’s virtual warehouse and supplier maintain its' stock, prices and product information. Retailers must provide the catalog id that they have created for you.
Publishing products to retailer can be done one-by-one per retailer or with a batch to multiple retailers.
Important is to mark down retailerId to whom you are publishing, catalog id that is provided by that retailer and productId.
PUT {{glueApiUrl}}/v3/inventory/balances
[ { "productExternalId": "Example-product-01", "retailerId": "1531864-4", "catalogExternalId": "Retailer-1531864-4-catalog-to-Supplier-C", "quantity": 10, "wholesalePrice": 23.4, "currency": "EUR" }, { "productExternalId": "Example-product-01", "retailerId": "9999999-2", "catalogExternalId": "Retailer-9999999-2-catalog-to-Supplier-C", "quantity": 20, "wholesalePrice": 25.6, "currency": "EUR" }, { "productExternalId": "Example-product-02", "retailerId": "9999999-2", "catalogExternalId": "Retailer-9999999-2-catalog-to-Supplier-C", "quantity": 5, "wholesalePrice": 1.6, "currency": "EUR" } ]
Find full schema description here.
See product data with all balances (to whom product is published).
To see what product data has been published to GLUE use GET {{glueApiUrl}}/ecommerce/v3/inventory.
Full product catalog is returned with balances section that can have multiple entities. One for each catalog.
NB! If there are a large number of products, it is recommended to use compression header when sending the request.
Accept-Encoding: gzip,deflateExample response
{ "links": [], "content": [ { "product": { "externalId": "Example-product-01", "supplierId": "0109357-9", "eanCode": "1234567891005", "recommendedRetailPrice": 12, "unitOfMeasure": "KPL", "vatPercentage": 20, "measurements": { "weight": 1.43, "length": 0.2, "width": 0.065, "height": 0.45, "volume": 0.515 }, "isFragile": false, "isDangerousGoods": true, "hasBestBeforeDate": true, "hasWarranty": false, "warrantExpiration": 240, "warrantSerialControlled": false, "descriptions": { "en": { "name": "Fishing boots", "shortDescription": "Green fishing boots", "description": "Longer description for these good fishing boots", "supplier": "Nokia", "attachments": [ { "type": "marketing", "uri": "https://ae01.alicdn.com/kf/Hcdd71b50fe274a299edbfcf4755fa8d9m/Outdoor-Long-Waterproof-Fishing-Boots-Breathable-Fishing-Waders-Boot-Soft-and-comfortable-Fishing-Wading-Shoes-Rubber.jpg_Q90.jpg_.webp", "contentType": "jpg", "name": "Picture 1" } ], "specifications": [ { "type": "Tehnical data", "properties": [ { "name": "Operating voltage", "value": "220", "specifier": "V", "description": "Description if needed" }, { "name": "Colour", "value": "White" } ] }, { "type": "Measures", "properties": [ { "name": "Waist", "value": "94", "specifier": "cm" }, { "name": "Size", "value": "M", "specifier": "EU" } ] } ], "comments": [ { "name": "Maintenance", "value": "Wash with fresh water after usage.", "type": "Instructions" } ] }, "fi": { "name": "Saappaat", "shortDescription": "Vihreät saappaat", "description": "Pidempi kuvaus näistä hyvistä kalasaappaista", "supplier": "Nokia", "attachments": [ { "type": "marketing", "uri": "https://ae01.alicdn.com/kf/Hcdd71b50fe274a299edbfcf4755fa8d9m/Outdoor-Long-Waterproof-Fishing-Boots-Breathable-Fishing-Waders-Boot-Soft-and-comfortable-Fishing-Wading-Shoes-Rubber.jpg_Q90.jpg_.webp", "contentType": "jpg", "name": "Picture 1" } ], "specifications": [ { "type": "Tehnical data", "properties": [ { "name": "Operating voltage", "value": "220", "specifier": "V", "description": "Description if needed" }, { "name": "Colour", "value": "White" } ] }, { "type": "Measures", "properties": [ { "name": "Waist", "value": "94", "specifier": "cm" }, { "name": "Size", "value": "M", "specifier": "EU" } ] } ], "comments": [ { "name": "Huolto", "value": "Pese puhtaalla vedellä käytön jälkeen.", "type": "Ohjeet" } ] } }, "categories": { "en": [ "Shoes" ], "fi": [ "Kengät" ] } }, "balances": [ { "productExternalId": "Example-product-01", "eanCode": "1234567891005", "retailerId": "1531864-4", "catalogExternalId": "Catalog1", "quantity": 9.0, "allocated": 1.0, "wholesalePrice": 23.4 } ] }, { "product": { "externalId": "Example-product-02", "supplierId": "0109357-9", "eanCode": "1234567891005", "recommendedRetailPrice": 12, "unitOfMeasure": "KPL", "vatPercentage": 20, "measurements": { "weight": 1.43, "length": 0.2, "width": 0.065, "height": 0.45, "volume": 0.515 }, "isFragile": false, "isDangerousGoods": true, "hasBestBeforeDate": true, "hasWarranty": false, "warrantExpiration": 240, "warrantSerialControlled": false, "descriptions": { "en": { "name": "Fishing boots", "shortDescription": "Green fishing boots", "description": "Longer description for these good fishing boots", "supplier": "Nokia", "attachments": [ { "type": "marketing", "uri": "https://ae01.alicdn.com/kf/Hcdd71b50fe274a299edbfcf4755fa8d9m/Outdoor-Long-Waterproof-Fishing-Boots-Breathable-Fishing-Waders-Boot-Soft-and-comfortable-Fishing-Wading-Shoes-Rubber.jpg_Q90.jpg_.webp", "contentType": "jpg", "name": "Picture 1" } ], "specifications": [ { "type": "Tehnical data", "properties": [ { "name": "Operating voltage", "value": "220", "specifier": "V", "description": "Description if needed" }, { "name": "Colour", "value": "White" } ] }, { "type": "Measures", "properties": [ { "name": "Waist", "value": "94", "specifier": "cm" }, { "name": "Size", "value": "M", "specifier": "EU" } ] } ], "comments": [ { "name": "Maintenance", "value": "Wash with fresh water after usage.", "type": "Instructions" } ] }, "fi": { "name": "Saappaat", "shortDescription": "Vihreät saappaat", "description": "Pidempi kuvaus näistä hyvistä kalasaappaista", "supplier": "Nokia", "attachments": [ { "type": "marketing", "uri": "https://ae01.alicdn.com/kf/Hcdd71b50fe274a299edbfcf4755fa8d9m/Outdoor-Long-Waterproof-Fishing-Boots-Breathable-Fishing-Waders-Boot-Soft-and-comfortable-Fishing-Wading-Shoes-Rubber.jpg_Q90.jpg_.webp", "contentType": "jpg", "name": "Picture 1" } ], "specifications": [ { "type": "Tehnical data", "properties": [ { "name": "Operating voltage", "value": "220", "specifier": "V", "description": "Description if needed" }, { "name": "Colour", "value": "White" } ] }, { "type": "Measures", "properties": [ { "name": "Waist", "value": "94", "specifier": "cm" }, { "name": "Size", "value": "M", "specifier": "EU" } ] } ], "comments": [ { "name": "Huolto", "value": "Pese puhtaalla vedellä käytön jälkeen.", "type": "Ohjeet" } ] } }, "categories": { "en": [ "Shoes" ], "fi": [ "Kengät" ] } }, "balances": [ { "productExternalId": "Example-product-02", "eanCode": "1234567891005", "retailerId": "1531864-4", "catalogExternalId": "Catalog1", "quantity": 7.0, "allocated": 3.0, "wholesalePrice": 23.4, "currency": "EUR" }, { "productExternalId": "Example-product-02", "eanCode": "1234567891005", "retailerId": "9999999-2", "catalogExternalId": "Catalog999", "quantity": 24, "wholesalePrice": 25.6, "currency": "EUR" } ] } ], "page": { "size": 2000, "totalElements": 2, "totalPages": 1, "number": 0 } }
Find full schema description here.
See only balance information for published catalogs.
Compared to previous request GET {{glueApiUrl}}/ecommerce/v3/inventory/balances
is returning only
balance object from the product. This has much more smaller response and can be used to check stock balances on
daily bases. Response contains again balances objects for all different catalogs. So one product can appear multiple
times because it has been published to many catalogs.
{ "links": [], "content": [ { "productExternalId": "Example-product-02", "eanCode": "1234567891005", "retailerId": "1531864-4", "catalogExternalId": "Catalog1", "quantity": 7.0, "allocated": 3.0, "wholesalePrice": 23.4, "currency": "EUR" }, { "productExternalId": "Example-product-02", "eanCode": "1234567891005", "retailerId": "9999999-2", "catalogExternalId": "Catalog999", "quantity": 24, "wholesalePrice": 25.6, "currency": "EUR" }, { "productExternalId": "Example-product-01", "eanCode": "1234567891005", "retailerId": "1531864-4", "catalogExternalId": "Catalog1", "quantity": 9.0, "allocated": 1.0, "wholesalePrice": 23.4 } ], "page": { "size": 2000, "totalElements": 3, "totalPages": 1, "number": 0 } }
Find full schema description here.
GET balances request can include also a field "allocated"
. This field indicates the amount of products
reserved for
open orders in specific catalog. When orders are processed then allocated value is moving towards 0. If order gets
cancelled then allocated value is put back to available "quantity"
.
There is an option to filter out specific retailer or catalog information with parameters.
Find full schema description and parameters here.
Simplest way to update stock balance would be to use PUT {{glueApiUrl}}/v3/inventory/balances
[ { "productExternalId": "Example-product-02", "catalogExternalId": "Catalog1", "retailerId": "1531864-4", "quantity": 200 }, { "productExternalId": "Example-product-02", "catalogExternalId": "Catalog999", "retailerId": "9999999-2", "quantity": 300 } ]
Note that when sending this way allocations will still be there. If you want to release allocations then you need
to send also "allocated": 0
Same message can be used to change the price for specific retailer or for all.
PUT {{glueApiUrl}}/v3/inventory/balances
[ { "productExternalId": "Example-product-02", "catalogExternalId": "Catalog1", "retailerId": "1531864-4", "wholesalePrice": 12 }, { "productExternalId": "Example-product-02", "catalogExternalId": "Catalog999", "retailerId": "9999999-2", "wholesalePrice": 13 } ]
Result:
GET {{glueApiUrl}}/v3/inventory/balances
[ { "productExternalId": "Example-product-02", "eanCode": "1234567891005", "retailerId": "1531864-4", "catalogExternalId": "Catalog1", "quantity": 200, "allocated": 3.0, "wholesalePrice": 12, "currency": "EUR" }, { "productExternalId": "Example-product-02", "eanCode": "1234567891005", "retailerId": "9999999-2", "catalogExternalId": "Catalog999", "quantity": 300, "allocated": 5, "wholesalePrice": 13, "currency": "EUR" } ]
Find full schema description and parameters here.
If you don't specify the catalogExternalId then stock quantity will be updated to all reatilers to whom you have published the product(s).
Note that when sending request this way allocations will still be there. If you want to allocations then you need to send also "allocated": 0 with the payload.
PUT {{glueApiUrl}}/v3/inventory/balances
[ { "productExternalId": "Example-product-01", "quantity": 100 }, { "productExternalId": "Example-product-02", "quantity": 120 } ]
Products can be removed from retailers catalogs with DELETE
request.
Example:
DELETE
{{glueApiUrl}}/v3/inventory/balances?productExternalId=Example-product-02&catalogExternalId=Catalog1&retailerId=1531864-4
If making request without specifying catalog and/or retailer then product will be removed from all the catalogs where it’s in.
Find full schema description and parameters here.
To delete product(s) permanently you can use DELETE {{glueApiUrl}}/v3/inventory
[ { "product": { "externalId": "Example-product-02", "status": "EOS" } } ]
In this case available balance is set to 0
and product status is
changed to EOS
.
Now retailers will still receive this product in their GET responses but the status will be shown as EOS and available balance is 0.
This method allows retailers to remove products that are no longer in sails from their system.
After DELETE command you will not receive this product in GET responses anymore.
Find full schema description and parameters here.
Retailer can get product data with or without balances.
Some examples for mostly used requests are:
Note that API returns max 2000 objects per request. Where there is page object present in response you need to
check
the totalElements
and totalPages
number. And loop through the pages if needed with
providing &page=0 or &page=1 etc
as a parameter. First page is 0.
"page": { "size": 2000, "totalElements": 3322, "totalPages": 2, "number": 0 }
GET {{glueApiUrl}}/v3/catalogs/{catalogId}/products
will return all products with descriptions and
balances in that catalog.
Products with status = EOS where delete less then 14 days ago. Products that where delete more then 14 days ago are not included in the response.
There is also option to filter and search based on the parameters found here.
NB! If there are a large number of products, it is recommended to use compression header when sending the request.
Accept-Encoding: gzip,deflate
GET {{glueApiUrl}}/v3/catalogs/{catalogId}/balances
will return only balance objects for that catalog.
Filtering can be applied.
See full spec here.
GET {{glueApiUrl}}/v3/catalogs/{catalogId}/products/?productExternalId={externalId}
will return only
specified product. Search parameter eanCode
is also supported.
Note that multiple values can be given to the parameter separated with comma.
?productExternalId={externalId},{externalId},{externalId}
See full spec here.
GET {{glueApiUrl}}/v3/catalogs/{catalogId}/balances/?productExternalId={externalId}
will return only
specified product. Search parameter eanCode is also supported.
Note that multiple values can be given to the parameter separated with comma.
?productExternalId={externalId},{externalId},{externalId}
See full spec here.
GET {{glueApiUrl}}/v3/catalogs/{catalogId}/balances?modifiedFromDate=2021-05-25T09:00:00.000Z
Will return only products with balances that have been changed after provided timestamp. This will also return products in case only order has been placed because available quantity has changed. But will return also result when supplier has updated quantities.
See full spec here.