---
title: "Product / Content Upload API"
method: POST
path: "/v1/products"
tags: ["Product / Content APIs"]
---

# Product / Content Upload API

`POST /v1/products`

Bulk API to insert Product records. This API endpoint accepts POST requests with JSON data
containing a list of Product / Content records wrapped in a dictionary:
```
POST /v1/products

{"data": [product_1, product_2, product_3]}
```

Each product is uniquely identified by its `product_id`. If a record with the same `product_id`
already exists in the dataset, the existing one will be **replaced** by the insertion (no
partial update is allowed at this time). We recommend limiting your calls to around 100
records at a time to avoid memory issues or timeout risks.

### Schema validation
This API validates the inserted records against the API schema; any schema error will cause
the whole request to fail (`status_code=422`), and none of the records will be inserted. You
should check the `response.errors` field to see if there are any errors. For example,
the response below means there are no errors (`status_code=200`):

```json
{
  "message": "success",
  "data": {
    "task_id": "{task_id}"
  }
}
```

A common source of errors when uploading Product records is that the custom attributes' data
types are not consistent with the data types of the existing records. In such cases,
you can check the individual error message in the `data` array. For example, if there is an
error regarding the second record you tried to insert, the response might look like:

```json
{
  "errors": true, // there are errors. please check!
  "data": [
    "data.0.custom_attributes.designer is invalid. Its data type is not consistent with other records",
    "data.0.product_id is invalid. The attribute expected to be of type 'string', but 'array' is given.",
    "data.0.created_at is invalid. The attribute should match 'date-time' format."
  ]
}
```

### Internationalization (I18N)
Miso has the built-in support for majority of Western European languages, including `English`, `French`, `German`,
`Spanish`, `Italian`, `Dutch`, `Russian`, and `Ukrainian`, as well as, major Asian languages, including `Mandarin`
 (both Simplified and Traditional), `Japanese`, and `Korean`.

In Dojo, you can choose the *Primary Language* for your product catalog (default is English).
However, you can also have more than one language in your product catalog that is
beyond your primary languages using the `i18n_$LN` fields (replace `$LN` with the [two-letter language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) of your choice),
and let Miso apply the language-specific preprocessing for you, such as tokenization, stemming, elision
removal, folding, decompounding, and traditional to simplified Chinese conversion.

For example, you may have a product called "Arizona, Green Tea with Ginseng & Honey" in your catalog, and you also
sell it in your Spanish, French, and Chinese sites, and want your customers to be able to search for this product
in their native languages.

In this case, your product records will like the following sample record, where English is the primary language of
the record, and `i18n_es`, `i18n_fr`, `i18n_zh` fields contain product details in their corresponding languages.
```javascript
{
    "product_id": "arizona-ginseng-honey",
    // the primary language is English
    "title": "Arizona, Green Tea with Ginseng & Honey",
    // ... other product details in English
    "i18n_es": {
       "title": "AriZona, Té verde con ginseng y miel"
        // ... other product details in Spanish
    },
    "i18n_fr": {
       "title": "AriZona - Thé Vert Aromatisé au Miel"
        // ... other product details in French
    },
    "i18n_zh": {
       "title": "美國ARIZONA亞歷桑納 - 蜂蜜人蔘綠茶"
        // ... other product details in Chinese
    }
 }
```
In this way, your customer can find this product with any of the following search queries
without additional configuration:
* `arizona green tea`
* `arizona te verde`
* `arizona the vert`
* `arizona 綠茶`

The similar concept applies to Autocomplete as well. You can specify a `language` parameter
in the requests to Autocomplete API, and the autocomplete results for the specific language
will be returned.

## Request body

- ProductBulkIn
  - `data` ProductRecord[], required
    - `product_id` string, required — The unique identifier for this product. The Id can be in any format you use in your product database (e.g. the product's SKU, UPC, or UUID or serial number). We will use this Id to track how users interact with products and content in the Interactions records you upload to Miso. It is important to keep the Id consistent between two datasets. For products that have multiple variants, you should have a unique `product_id` for each variant, and use `product_group_id` to group them together. For example, for a T-shirt with SKU `123ABC` that comes in 4 sizes: `S`, `M`, `L`, `XL`, we should create four different products: ``` { "product_id": "123ABC-S", "product_group_id" "123ABC" } { "product_id": "123ABC-M", "product_group_id" "123ABC" } { "product_id": "123ABC-L", "product_group_id" "123ABC" } { "product_id": "123ABC-XL", "product_group_id" "123ABC" } ``` * Constraints * Can't contain `,` * Can't start with `_` * Length <= 512
    - `product_group_id` string — The `product_group_id` is used to prevent the same product (but a different variant) from showing multiple times in the search or recommendation results. When one product has multiple variants (for example, different sizes, colors, or materials), you should assign a unique product_id to each variant, but assign the same `product_group_id` to all of them. If `product_group_id` is not given, we default to the value of `product_id`.
    - `parent_id` string — The `parent_id` is used to declare a parent-child relationship between two "Products". Such relationships are common in marketplaces and content media sites with user generated contents. For example, an E-commerce marketplace (such as E-bay or Amazon) may have "Shops" (as parents) and "Merchandises" (as children), and a social streaming site, such as YouTube, may have "Channel" (as parents) and "Video" (as children). In these sites, both entities can be modeled as "Products", and can both be returned in Search and Recommendation APIs. Declaring the parent-child relationships allows Miso to automatically propagate interactions from one product to the other. For example, when a user "watch" a Video, Miso will propagate this signal to the Channel which publishes this Video, even if users do not directly interact with the Channel page. Such implicit interactions are particularly useful when making recommendations for Channel because it gives Miso much more information about users' interests to different Channels than solely relying on users' direct interactions with the them, which happens less often. `parent_id` needs to be a non-empty string referring to the `product_id` of the parent product. The parent product can be uploaded in a separate batch, and does not need to exist before its children products. The implicit interactions will only exist during Miso's training process, and will not show up in the Interaction dataset.
    - `related_ids` string[] — The product_id or product_group_id of other products that are related to this Product
    - `type` string — The `type` of product. This is for sites that have more than one type of product or content that they want their users to interact with. If your site has only one type of product, you can leave this field out. A classic example is travel sites, which have both *hotel* and *flight* sales. It is also useful for sites that let users interact with products as well as *product bundles*. For example, on YouTube, each video is a product that users can watch, while each channel, containing multiple videos, is also a product that users can subscribe to. For model quality, it is preferable to model all these distinct product types in the same data set, so that a user's interests for one type of product can inform their interests in another type of products. The `type` field helps Miso make these distinctions.
    - `title` string — The title of the product. During a search, Miso will put predictive weight behind the title, because it is often the main way users identify a product.
    - `description` string — The `description` text of the product. Miso assumes `description` contains longer textual content than other string-based fields. For example, term frequency matters more here than in a field like the title. Miso’s semantic understanding can extract a lot of valuable information from having a product description that is plain-spoken and detailed.
    - `short_description` string — The `short_description` text of the product. Miso assumes `short_description` contains a shorter version or a summary of the `description` field.
    - `language` string — The `language` of the product description and content in [two-letter ISO 639-1 code]( https://en.wikipedia.org/wiki/ISO_639-1). For example, English = `en`, Chinese = `zh`. Miso will use this field to determine the proper way to index the product description. If this field is not specified, we will determine the language automatically. We also use the language field to determine users’ interests in content of different languages. This is particularly important for content media sites that have different languages of content. * Constraints: * [Two-letter ISO 639-1 code](https://en.wikipedia.org/wiki/ISO_639-1). For example, English = `en`, Chinese = `zh`.
    - `created_at` union — The time when the product was first created or became available on your site as an ISO-8601 date or datetime string.
      - string, date-time
      - string, date
    - `published_at` union — The time when the product was published as an ISO-8601 date or datetime string.
      - string, date-time
      - string, date
    - `updated_at` union — The time when the product was updated as an ISO-8601 date or datetime string.
      - string, date-time
      - string, date
    - `categories` array[] — In Miso, you describe a product or content category as a hierarchical list of strings from broad to narrow, called a `category`. (See the `category_page_view` interaction.) Use the `categories` field of products to specify the hierarchical category or categories that the product belongs to. A product may belong to only a single `category`, or multiple. For example, a product could be in both: * *Toys & Games > Toys > Dolls, Playsets & Toy Figures > Stuffed Animals*, and * *Arts & Entertainment > Hobbies & Creative Arts > Collectibles*. This field should be a list of a list of strings, where category levels go from broad to narrow, such as: ``` {"categories": [ // the first category the product belongs to ["TOYS & GAMES", "TOYS", "DOLLS, PLAYSETS & TOY FIGURES", "STUFFED ANIMALS"], // the second category the product belongs to ["ARTS & ENTERTAINMENT", "HOBBIES & CREATIVE ARTS", "COLLECTIBLES"] ] } ``` If your product taxonomy has only one single level, that is not an issue: ``` {"categories": [ // the first category the product belongs to ["Toys"], // the second category the product belongs to ["Collectibles"] ] } ``` The categories are optional, but very important for profiling the products and tracking users' preferences. (See also the `category_page_view` interaction)
      - string[]
    - `tags` string[] — The tags that have been associated with the product. For example: ``` {"tags": ["TAG_1", "TAG_2", ...]} ```
    - `url` string, uri — Url to the product detail page. This is for displaying the product in your Dojo Sandboxes and is not used for Engine training. It is optional, but strongly recommended for a better Sandbox experience.
    - `cover_image` string, uri — The URL of the cover image of the product. This is for displaying the product in your Dojo Sandboxes and is not used for Engine training. It is optional, but strongly recommended for a better Sandbox experience.
    - `original_price` number — The (original) price of the product. We only use this number to calculate the amount of discount, and use that to profile user behaviors. * Constraints: * Need to be a number, but no constraint on the range of the number
    - `sale_price` number — The sale price of the product. * Constraints: * Need to be a number, but no constraint on the range of the number
    - `margin` number — The margin of the product. Note that for our margin optimization algorithm to work, the margin you specify here does not need to be the actual dollar amount, but it needs to be something in proportion to that. * Constraints: * Need to be a number, but no constraint on the range of the number
    - `size` string — The size of the product. For example, for an eCommerce site that sells T-shirts, each T-shirt might come in several different sizes. In this case, we recommend that you should create one product entry for each size variant. When Miso generate search or recommendation results, we use the `product_group_id` to remove different variants of the same product, and only show the variant that the user is most likely to buy.
    - `color` string — The color of the products. Similarly to `size`, when `color` of the products matters, it is recommended to create one product for each color variant of a product. When Miso generate search or recommendation results, we use the `product_group_id` to remove variants of the same product, and only show the variant that the user is most likely to buy.
    - `material` string — The material of the products. Similarly to `size` and `color`, if `material` of the product matters and there are multiple material variants, we should create one product for each material variant. When Miso generates search or recommendation results, we use the `product_group_id` to remove variants of the same product, and only show the variant that the user is most likely to buy.
    - `condition` 'NEW' | 'USED' | 'REFURBISHED' — The condition of the product. By default, we assume `condition`= `NEW`
    - `brand` string — The brand of the product.
    - `authors` string[] — The author(s) of the product or content asset. This field needs to be an array of strings.
    - `publishers` string[] — The publisher(s) of the product or content asset. This field needs to be an array of strings.
    - `collections` string[] — The collection(s) the product belongs to.
    - `availability` 'IN_STOCK' | 'OUT_OF_STOCK' | 'PRE_ORDER' — The availability of the product. Miso mainly uses `availability` to filter `OUT_OF_STOCK` items out of its recommendations. As a default, we assume the product is `IN_STOCK`.
    - `location` union — The location information of the product (e.g. for hotels or restaurants). We support geolocation filtering and sorting when creating search and recommendation results if location information is given.
      - LocationInformation[]
        - `lat` number, required
        - `lon` number, required
      - LocationInformation
        - `lat` number, required
        - `lon` number, required
    - `rating` number — The overall rating of the product in the range of [0, 5]. If you use a different rating scale, please convert it to the range of [0, 5].
    - `html` string — The HTML content of the product. Miso will search against this field and apply semantic understanding in a way that is similar to the `description` field, but with HTML tags removed.
    - `subtitle` string — The subtitle of the product (usually for contents).
    - `headers` string[] — The headers in the content. This usually corresponds to `<h1>`, `<h2>`, `<h3>` ... tags in HTML. This field need to be an array of strings
    - `paragraphs` string[] — The text paragraphs in the content. This usually corresponds to `<p>` tags in HTML. This field need to be an array of strings
    - `anchors` string[] — The anchor texts paragraphs in the content. This usually corresponds to `<a>` tags in HTML. This field need to be an array of strings
    - `children` ChildrenObject[] — Children objects of the product, such as chapters of a book, or sections of a podcast. Children are only useful for long-form contents, and are only used for snippet extraction purpose.
      - `id` string, required
      - `url` string
      - `title` string
      - `description` string
      - `html` string
      - `headers` string[]
      - `custom_attributes` object
    - `enable_question_answering` boolean — Whether to enable question answering capability against the `html` field.
    - `custom_attributes` object — Dictionary of custom attributes for the product. You can specify attributes specific to your business in a `{"KEY":VALUE}` format, where `KEY` must be a string, and `VALUE` can be: * a `bool` * a `string` or an `array of string` * a `number` or an `array of numbers` * an `array of objects` * `null` For example, a video streaming site using Miso may have the movie *Jumanji* with the following custom attributes: ``` { "custom_attributes": { "cast": [ "Robin Williams", "Jonathan Hyde", ... ], "director": "Joe Johnston", "genres": [ "Adventure", "Fantasy", "Family" ], "filming_locations": [ {"country": "USA", "state": "New Hampshire", "city": "Keene"}, {"country": "Canada", "state": "British Columbia", "city": "Vancouver"} ], "popularity": 7.439, "adult": false } } ``` **The custom attribute types need to be consistent across every record in the dataset**. For instance, in the example above, the **cast** attribute needs to be a `string` or `an array of string` or `null` for every record in the dataset that specify **cast** attribute. Similarly, the popularity attribute needs to be a `number`, `an array of numbers`, or `null` for every record in the dataset that specifies the popularity attribute. If you try to insert a record with an incompatible data type, the insertion for that record will fail.

## Response `200`

Successful Response

- CreateResponse
  - `message` string, required — Human-readable message
  - `data` TaskId, required
    - `task_id` string, required

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `422` — Unprocessable Entity
- `500` — Internal Server Error

---

[API](https://skmtc.dev/askmiso/apis/miso-api.md) · [All operations](https://skmtc.dev/askmiso/apis/miso-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/askmiso/miso-api/revisions/f2fa5ba6025f/schema)
