Skip to main content

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 or a brand reference which can be retrieved from the /api/v2/brands/ endpoint.

Updates on this doc:

Jul 12 2021 brand_id is deprecated. Please use brand attribute for uploading products endpoint, which acccepts value of a brand ID (integer) or a brand reference (string).

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:

  1. Pre-validate the data to be uploaded
  2. Format the data to be uploaded into the specified JSON structure
  3. Upload the JSON data to the API
  4. 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:

  1. Format Checking:
    • Verify the data contains all required fields.
    • Verify that all items have the same # of fields.
  2. 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:

  1. Process the data and create an array of JSON objects.
  2. Create batches 1 object each.
  3. Ignore previously uploaded rows.
  4. Convert all values to strings.
  5. Send a POST request to the API /api/v2/products/
  6. 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.

AttributeRequired?Description
skurequiredUnique product SKU in the company.
brandoptionalThe ID (integer) or reference (string) of the brand. They can be retrieved by calling /api/v2/brands/ endpoint.
namerequiredName of the product.
descriptionoptionalA brief description of the product.
client_urloptionalA product URL that may be used to redirect codes if a campaign is not active for the product.
imageoptionalInclude a product image, typically used on STC landing pages. If not set, the brand image will be used. To upload images use multipart.
campaignoptionalThe ID of an existing campaign in the company to which this product must be added.

Example Parameters POST (application/json) with brand ID

{
"sku": "PR1",
"brand": 50,
"name": "Product One",
"description": "The first product in a line of many others.",
"client_url": "http://www.examplebrand.com/productone"
}

Example Parameters POST (application/json) with brand reference

{
"sku": "PR2",
"brand": "some brand",
"name": "Product Two",
"description": "The second product in a line of many others.",
"client_url": "http://www.examplebrand.com/producttwo"
}

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": {
"id": 50,
"name": "cool brand name",
"image": "http://www.examplebrand.com/brand_image.jpg"
},
"company": {
...
},
"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 or brand reference
  • Required fields left empty

Product is posted with an invalid brand ID or reference:

{
"brand": [
"Invalid Brand reference or id."
]
}

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.

AttributeRequired?Description
skuoptionalUnique product SKU in the company.
brandoptionalThe ID (integer) or reference (string) of the brand. They can be retrieved by calling /api/v2/brands/ endpoint.
nameoptionalName of the product.
descriptionoptionalA brief description of the product.
client_urloptionalA product URL that may be used to redirect codes if a campaign is not active for the product.
imageoptionalInclude a product image, typically used on STC landing pages. If not set, the brand image will be used. To upload images use multipart.
campaignoptionalThe 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"
},
"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": []
}