Upload Products
Overview
This document covers the process of uploading products with the Scantrust API. You will need:
A UAT token with the right permissions: The UAT token needs to have access to the following permissions:
product_create
product_delete
product_edit
product_view
The UAT token must be set in the header fields of all requests as described in Authentication & Tokens.
You will also need at least one Brand set up in the Portal: each product you create needs to be assigned to a brand. This is done with a brand ID which can be retrieved from the /api/v2/brands/
endpoint.
Your Upload Handler
You will need to write an upload handler which will communicate with the API endpoint, handle the data to be uploaded and processes the response from the server. The job of the upload handler is to:
- Pre-validate the data to be uploaded
- Format the data to be uploaded into the specified JSON structure
- Upload the JSON data to the API
- Process the response
Pre-Validation of uploaded file
It is recommended to pre-validate the data to be uploaded. This prevents unnecessary calls to the API. The following minimum pre-validation should be done:
- Format Checking:
- Verify the data contains all required fields.
- Verify that all items have the same # of fields.
- Preliminary Error Checking:
- Verify that no ‘SKU’ value is duplicated.
- Verify that no ’SKU’ value is blank.
Format data to be uploaded
Data must be uploaded using JSON as the format. The API will accept only one product per call. Therefore the data must be split into batches of max 1 item per POST. It is recommended to keep a log file containing the SKU of previously uploaded products so they can be skipped when uploading again.
General flow:
- Process the data and create an array of JSON objects.
- Create batches 1 object each.
- Ignore previously uploaded rows.
- Convert all values to strings.
- Send a POST request to the API
/api/v2/products/
- save the SKU as 'uploaded' in a logfile:
- Subsequent runs should ignore all keys that are in the 'uploaded' file.
API Design /api/v2/products/
POST: /api/v2/products/
Uploads a product for any brand the company owns and assigns it to the right campaign. One item per POST is allowed. Multiple requests can be made to update more items.
Attribute | Required? | Description |
---|---|---|
sku | required | Unique product SKU in the company. |
brand_id | required | Foreign Key to a brand owned in the company. This value must be passed as an ID. A brand ID can be retrieved by doing a GET call to the /api/v2/brands/ endpoint. |
name | required | Name of the product. |
description | optional | A brief description of the product. |
client_url | optional | A product URL that may be used to redirect codes if a campaign is not active for the product. |
image | optional | Include a product image, typically used on STC landing pages. If not set, the brand image will be used. To upload images use multipart. |
campaign | optional | The ID of an existing campaign in the company to which this product must be added. |
Example Parameters POST (application/json)
{
"sku": "PR1",
"brand_id": "50",
"name": "Product One",
"description": "The first product in a line of many others.",
"client_url": "http://www.examplebrand.com/productone"
}
Response (200): Status OK
When a product is successfully posted, a response will be given.
{
"id": 6629,
"uuid": "1c262803-072c-4809-a957-39dd8c807d78",
"sku": "PIG12345",
"image": null,
"name": "Hello Name",
"description": "This is a test",
"label": "Test",
"brand": {
...
},
"company": {
...
},
"brand_id": 1187,
"creation_date": "2021-04-09T04:48:48.956138Z",
"client_url": "http://www.scantrust.com",
"is_archived": false,
"campaign": 575
}
Response (400) : Invalid Data Format
An exception will be raised when any of the following is detected in a product:
- Duplicate SKU
- Invalid brand ID
- Required fields left empty
Product is posted with an invalid brand ID:
{
"brand_id": ["Invalid pk \"686\" - object does not exist."]
}
When product is posted or patched with when an SKU already exists:
{ "sku": ["SKU must be unique within this company."] }
PATCH: /api/v2/products/{id}/
Endpoint to patch (update) existing products. Any number of editable fields can be patched and adjusted for this specific product. Updating requires the ID of the product to be appended to the endpoint URL. When patching, all fields are optional and only the posted fields will be adjusted.
Attribute | Required? | Description |
---|---|---|
sku | optional | Unique product SKU in the company. |
brand_id | optional | Foreign Key to a brand owned in the company. This value must be passed as an ID. A brand ID can be retrieved by doing a GET call to the /api/v2/brands/ endpoint. |
name | optional | Name of the product. |
description | optional | A brief description of the product. |
client_url | optional | A product URL that may be used to redirect codes if a campaign is not active for the product. |
image | optional | Include a product image, typically used on STC landing pages. If not set, the brand image will be used. To upload images use multipart. |
campaign | optional | The ID of an existing campaign in the company to which this product must be added. |
Example Parameters PATCH /api/v2/products/50/ (application/json)
{
"description": "The first product in a line of many others.",
"client_url": "http://www.examplebrand.com/productone"
}
This updates only the description and client_url of product with ID=50.
Upload images
To upload images Multipart
needs to be used. See the python example below:
product_id = 1
def patch_multipart(self, path, files, data, raw_resp=False):
resp = requests.patch(
url=self.server_url + path,
data=data,
files=files,
headers=self._auth()
)
if raw_resp:
return resp
self.validate_resp(resp)
return resp.json()
with open('image.jpeg', 'rb') as f:
files = {'image': ('image.jpeg', f)}
resp = self.server.patch_multipart('/api/v2/products/%s/' % product_id, data=None, files=files)
GET: /api/v2/products/?sku__exact={sku}
This endpoint can be used to retrieve a specific product ID by SKU. By passing ?sku__exact in the endpoint URL, the system will look for an exact match within the company's products. Only one result should be returned since SKU is unique per company.
Response (200): Status OK
When a product is successfully found, a response will be given. The results comes as a LIST. The first object in that list should be taken to know the ID.
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 959,
"uuid": "701b1a6f-e751-4c20-8012-028063322fb0",
"sku": "prod2",
"image": null,
"name": "Product #2",
"description": "",
"label": "Product #2",
"brand": {
"id": 749,
"name": "100 Brand",
"image": null
},
"company": {
"id": 871,
"uuid": "1fc1a571-1918-4f7d-b826-510752156cdf",
"name": "Test brand"
},
"brand_id": 749,
"creation_date": "2017-02-16T08:59:08.774705Z",
"client_url": "",
"is_archived": false,
"code_count": 0,
"active_code_count": 0,
"blacklisted_code_count": 0,
"campaign": {
"id": 188,
"name": "test campaign",
"description": "camp",
"is_archived": false
}
}
]
}
Example product not found:
{
"count": 0,
"next": null,
"previous": null,
"results": []
}