Canal products API
The products API from Canal — 5 operation(s) for products.
The products API from Canal — 5 operation(s) for products.
openapi: 3.0.3
info:
title: Rokt Catalog csv products API
version: 1.0.1
description: Integrate with Rokt Catalog
servers:
- url: https://api.shopcanal.com/platform
description: Rokt Catalog Storefront Public API
tags:
- name: products
paths:
/products/:
get:
operationId: products_list
description: '
**[Storefront Only]** Retrieve a paginated list of products accessible to your Storefront through your established Rokt Catalog connections.
This endpoint returns products from Suppliers with whom you have an **active and approved** partnership. It includes products you might have already added/linked to your Storefront platform, as well as other products listed by those Suppliers that are available to you based on your connection terms.
You can filter the results to view products exclusively from one Supplier by providing their Catalog `supplier_id` (UUID) as a query parameter.
Results are returned using cursor-based pagination (`PlatformPagination`). Available ordering fields include `created_at`, `updated_at`, and `title`. The default order is `-created_at`.
'
parameters:
- name: ordering
required: false
in: query
description: Which field to use when ordering the results.
schema:
type: string
- name: cursor
required: false
in: query
description: The pagination cursor value.
schema:
type: string
- in: query
name: supplier_id
schema:
type: string
format: uuid
description: Filter products by the Catalog ID of a specific connected Supplier.
- in: query
name: qa_review_complete
schema:
type: boolean
description: Filter products by whether they have been reviewed and approved.
tags:
- products
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedExternalProductList'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
post:
operationId: products_create
description: '
**[Supplier Only]** Create a new product listing within your Rokt Catalog Supplier account. This makes the product manageable through Catalog and potentially available to your connected Storefront partners.
The request body must conform to the `PushProductSerializer` structure. Key fields include:
`title` (string, required), `body_html` (string, product description), `product_type` (string), `vendor` (string), `tags` (string, comma-separated), and a list of `variants` (required, at least one).
Each object in the `variants` list requires `price` (decimal string), `sku` (string), `inventory_quantity` (integer), and option values (`option1`, `option2`, `option3`). `compare_at_price` (decimal string) is optional for sale pricing.
You can also include a list of `images`, each with a `src` (URL) and optional `position`.
Successfully creating a product (HTTP `201 Created`) makes it visible in your Catalog dashboard. Its availability to Storefronts depends on its listing status (`supplier_has_listed_on_canal` flag on variants) and the terms established with each partner.
The response body contains the full details of the newly created product and its variants, including their assigned Catalog IDs (UUIDs), using the `ProductSerializer`.
'
tags:
- products
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PushProduct'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/PushProduct'
multipart/form-data:
schema:
$ref: '#/components/schemas/PushProduct'
required: true
security:
- platformAppId: []
platformAppToken: []
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
/products/{id}/:
get:
operationId: products_retrieve
description: '
**[Storefront Only]** Retrieve comprehensive details for a single product, identified by its Rokt Catalog `ID` (UUID) in the URL path.
Access is restricted: this endpoint only returns data for products sourced from Suppliers with whom your Storefront has an **active and approved** partnership connection.
The response (`ExternalProductSerializer`) includes all product-level information (title, description, vendor, etc.), a list of associated `images`, and a list of `variants`.
Crucially, the variant information includes pricing (`price`, `compare_at_price`) and `inventory_quantity` that are specific to **your connection** with the Supplier, reflecting any agreed-upon terms or markups managed by Catalog.
If the provided product `ID` is invalid, or if the product belongs to a Supplier you are not actively connected with, a `404 Not Found` error is returned.
'
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- products
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ExternalProduct'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
put:
operationId: products_update
description: '
**[Supplier Only]** Update attributes of an existing product listing, identified by its Rokt Catalog `ID` (UUID) in the URL path.
This endpoint is used for modifying **product-level** details. Provide the fields you wish to change in the request body (e.g., `title`, `body_html`, `product_type`, `vendor`, `tags`).
**Important:** To modify variant-specific details like price, SKU, inventory, or options, you **must** use the dedicated `/variants/{variant_id}/` endpoint. Updates to variants are not supported here.
Changes made to product-level fields via this endpoint (like updating the description) are automatically synchronized to any connected Storefronts that are currently selling this product. This synchronization process runs **asynchronously** in the background.
A successful update returns `200 OK` with the complete, updated product details (including all variants) using the `ProductSerializer`.
'
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- products
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Product'
multipart/form-data:
schema:
$ref: '#/components/schemas/Product'
required: true
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
patch:
operationId: products_partial_update
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- products
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PatchedProduct'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/PatchedProduct'
multipart/form-data:
schema:
$ref: '#/components/schemas/PatchedProduct'
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
description: ''
delete:
operationId: products_destroy
description: '
**[Supplier Only]** Permanently remove a product listing, identified by its Rokt Catalog `ID` (UUID) in the URL path, from the Catalog platform.
**Warning:** This action is **irreversible**. Ensure you intend to delete this product permanently.
You can only delete products that are directly owned by your Supplier account. Attempting to delete a product belonging to another shop will result in a `403 Forbidden` error.
**Effect on Storefronts:** When a product is deleted, Catalog automatically **pauses** the corresponding product listings on any connected Storefronts that were actively selling it. An asynchronous task is initiated to inform these Storefronts about the product''s removal.
A successful deletion returns an HTTP `204 No Content` status with an empty response body.
'
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- products
security:
- platformAppId: []
platformAppToken: []
responses:
'204':
description: No response body
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
/products/{id}/reorder_variants/:
post:
operationId: products_reorder_variants_create
description: '
**[Supplier Only]** Update the display sequence of variants for a specific product. The product is identified by its Rokt Catalog `ID` (UUID) in the URL path.
The request body must contain a field named `variant_order`, which is a list of Catalog variant `ID`s (UUIDs) sorted in the desired display order (0-indexed).
**Requirement:** The `variant_order` list **must** include the IDs of **all** currently existing variants for the specified product. Omitting or adding incorrect IDs will result in a validation error (400 Bad Request).
This reordering affects how variants are presented within the Catalog platform (e.g., in the Supplier dashboard). It may also influence the display order on connected Storefronts if their integration respects the `position` attribute of the variants.
A successful update returns `200 OK` with the full product details (`ProductSerializer`), reflecting the new `position` values for each variant.
'
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- products
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ReorderVariant'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/ReorderVariant'
multipart/form-data:
schema:
$ref: '#/components/schemas/ReorderVariant'
required: true
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
/products/{id}/resync/:
post:
operationId: products_resync_create
description: '
Resynchronize a retailer (Shopkeep) product with its origin supplier product.
If `fields_to_resync` is provided, only those fields will be updated; otherwise all fields are resynced.
On success, returns the updated product data. If the resync is queued to run asynchronously (e.g. due to rate limits), returns a message indicating the resync has started.
'
parameters:
- in: path
name: id
schema:
type: string
required: true
tags:
- products
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ResyncShopkeepProduct'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/ResyncShopkeepProduct'
multipart/form-data:
schema:
$ref: '#/components/schemas/ResyncShopkeepProduct'
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/ResyncShopkeepProductResponse'
description: ''
'202':
content:
application/json:
schema:
$ref: '#/components/schemas/ResyncShopkeepProductResponse'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
/products/upsell_products/:
get:
operationId: products_upsell_products_list
description: '
**[Storefront Only]** Retrieve a paginated list of active products that are eligible for upselling.
This endpoint returns products from Suppliers with whom you have an active and approved partnership.
Products must meet the following criteria:
1) Have status=''active'',
2) Have at least one variant that is connected to a supplier variant, listed on Catalog, and not paused for selling,
3) Have passed ads eligibility checks,
4) Have at least one available variant in a non-deleted product set,
'
parameters:
- name: ordering
required: false
in: query
description: Which field to use when ordering the results.
schema:
type: string
- name: cursor
required: false
in: query
description: The pagination cursor value.
schema:
type: string
- in: query
name: supplier_id
schema:
type: string
format: uuid
description: Filter products by the Catalog ID of a specific connected Supplier.
tags:
- products
security:
- platformAppId: []
platformAppToken: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedExternalProductList'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'401':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: ''
components:
schemas:
ReorderVariant:
type: object
properties:
variant_order:
type: array
items:
type: string
format: uuid
required:
- variant_order
ResyncShopkeepProduct:
type: object
properties:
fields_to_resync:
type: array
items:
$ref: '#/components/schemas/FieldsToResyncEnum'
ResyncShopkeepProductResponse:
type: object
properties:
ok:
type: boolean
status:
type: string
nullable: true
shopify_product:
allOf:
- $ref: '#/components/schemas/Product'
nullable: true
required:
- ok
PatchedProduct:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
shop:
allOf:
- $ref: '#/components/schemas/Shop'
readOnly: true
variants:
type: array
items:
$ref: '#/components/schemas/Variant'
readOnly: true
body_html:
type: string
nullable: true
maxLength: 60000
handle:
type: string
nullable: true
maxLength: 258
image_src:
type: string
nullable: true
maxLength: 1043
images:
type: array
items:
$ref: '#/components/schemas/Image'
options:
nullable: true
product_type:
type: string
nullable: true
maxLength: 1044
updated_at:
type: string
format: date-time
readOnly: true
published_at:
type: string
format: date-time
nullable: true
status:
$ref: '#/components/schemas/Status2eaEnum'
title:
type: string
maxLength: 1029
vendor:
type: string
nullable: true
maxLength: 227
tags:
type: string
nullable: true
maxLength: 63750
permalink:
type: string
format: uri
nullable: true
maxLength: 2000
number_of_reviews:
type: integer
maximum: 2147483647
minimum: -2147483648
nullable: true
star_rating:
type: number
format: double
nullable: true
FieldsToResyncEnum:
enum:
- images
- product_title
- description
- tags
- variants
- vendor
- permalink
type: string
description: '* `images` - images
* `product_title` - product_title
* `description` - description
* `tags` - tags
* `variants` - variants
* `vendor` - vendor
* `permalink` - permalink'
InventoryPolicyEnum:
enum:
- continue
- deny
type: string
description: '* `continue` - continue
* `deny` - deny'
Image:
type: object
properties:
id:
type: string
position:
type: integer
src:
type: string
format: uri
display_src:
type: string
format: uri
nullable: true
width:
type: integer
height:
type: integer
canal_variant_ids:
type: array
items:
type: string
readOnly: true
variant_ids:
type: array
items:
type: string
origin_supplier_image_id:
type: string
format: uuid
nullable: true
required:
- canal_variant_ids
- src
PaginatedExternalProductList:
type: object
required:
- results
properties:
next:
type: string
nullable: true
format: uri
example: http://api.example.org/accounts/?cursor=cD00ODY%3D"
previous:
type: string
nullable: true
format: uri
example: http://api.example.org/accounts/?cursor=cj0xJnA9NDg3
results:
type: array
items:
$ref: '#/components/schemas/ExternalProduct'
Variant:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
shop:
allOf:
- $ref: '#/components/schemas/Shop'
readOnly: true
inventory_policy:
type: string
nullable: true
maxLength: 123
inventory_quantity:
type: integer
maximum: 2147483647
minimum: -2147483648
nullable: true
inventory_item_cost:
type: number
format: double
option1:
type: string
nullable: true
maxLength: 255
option2:
type: string
nullable: true
maxLength: 256
option3:
type: string
nullable: true
maxLength: 257
position:
type: integer
readOnly: true
price:
type: string
format: decimal
pattern: ^-?\d{0,10}(?:\.\d{0,2})?$
description: The price of the variant to be sold at.
compare_at_price:
type: string
nullable: true
maxLength: 128
origin_supplier_currency:
type: string
nullable: true
readOnly: true
title:
type: string
sku:
type: string
nullable: true
readOnly: true
upc:
type: string
nullable: true
maxLength: 253
grams:
type: number
format: double
nullable: true
weight:
type: number
format: double
nullable: true
weight_unit:
type: string
nullable: true
maxLength: 3
pause_selling:
type: boolean
origin_supplier_id:
type: string
nullable: true
readOnly: true
origin_supplier_name:
type: string
nullable: true
readOnly: true
available_for_ordering:
type: boolean
readOnly: true
supplier_sku:
type: string
nullable: true
readOnly: true
is_exclusive_offer:
type: boolean
description: An exclusive offer is a variant that is discounted lower than the variant's actual price on the supplier's website.
readOnly: true
sup_price:
type: string
nullable: true
description: The connected supplier variant's price, sourced from the supplier directly.
readOnly: true
sup_compare_at_price:
type: string
nullable: true
description: The connected supplier variant's compare-at price, sourced from the supplier directly.
readOnly: true
required:
- available_for_ordering
- id
- is_exclusive_offer
- origin_supplier_currency
- origin_supplier_id
- origin_supplier_name
- position
- price
- shop
- sku
- sup_compare_at_price
- sup_price
- supplier_sku
- title
PushProduct:
type: object
properties:
title:
type: string
body_html:
type: string
variants:
type: array
items:
$ref: '#/components/schemas/PushProductVariant'
permalink:
type: string
handle:
type: string
image_src:
type: string
images:
type: array
items:
$ref: '#/components/schemas/Image'
product_type:
type: string
tags:
type: string
vendor:
type: string
shopify_taxonomy:
type: string
nullable: true
is_listed:
type: boolean
default: true
status:
allOf:
- $ref: '#/components/schemas/PushProductStatusEnum'
default: active
required:
- title
- variants
Shop:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
email:
type: string
nullable: true
readOnly: true
phone:
type: string
nullable: true
maxLength: 128
name:
type: string
maxLength: 129
description:
type: string
nullable: true
maxLength: 6144
myshopify_domain:
type: string
maxLength: 128
province:
type: string
nullable: true
maxLength: 122
country:
type: string
maxLength: 64
domain:
type: string
nullable: true
maxLength: 128
display_domain:
type: string
nullable: true
readOnly: true
privacy_policy_url:
type: string
format: uri
nullable: true
maxLength: 500
terms_of_service_url:
type: string
format: uri
nullable: true
maxLength: 500
required:
- country
- display_domain
- email
- id
- myshopify_domain
- name
Status2eaEnum:
enum:
- active
- draft
- archived
- unlisted
type: string
description: '* `active` - active
* `draft` - draft
* `archived` - archived
* `unlisted` - unlisted'
Product:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
shop:
allOf:
- $ref: '#/components/schemas/Shop'
readOnly: true
variants:
type: array
items:
$ref: '#/components/schemas/Variant'
readOnly: true
body_html:
type: string
nullable: true
maxLength: 60000
handle:
type: string
nullable: true
maxLength: 258
image_src:
type: string
nullable: true
maxLength: 1043
images:
type: array
items:
$ref: '#/components/schemas/Image'
options:
nullable: true
product_type:
type: string
nullable: true
maxLength: 1044
updated_at:
type: string
format: date-time
readOnly: true
published_at:
type: string
format: date-time
nullable: true
status:
$ref: '#/components/schemas/Status2eaEnum'
title:
type: string
maxLength: 1029
vendor:
type: string
nullable: true
maxLength: 227
tags:
type: string
nullable: true
maxLength: 63750
permalink:
type: string
format: uri
nullable: true
maxLength: 2000
number_of_reviews:
type: integer
maximum: 2147483647
minimum: -2147483648
nullable: true
star_rating:
type: number
format: double
nullable: true
required:
- id
- shop
- title
- updated_at
- variants
PushProductStatusEnum:
enum:
- active
- draft
- archived
type: string
description: '* `active` - active
* `draft` - draft
* `archived` - archived'
PushProductVariant:
type: object
properties:
title:
type: string
price:
type: string
format: decimal
pattern: ^-?\d{0,10}(?:\.\d{0,2})?$
description: The price of the variant to be sold at.
compare_at_price:
type: string
format: decimal
pattern: ^-?\d{0,10}(?:\.\d{0,2})?$
nullable: true
description: The original price of the product from before the sale price. Should be greater than "price". If you elect to not allow sale price passthrough, Connected Storefronts will sell items at this price.
inventory_policy:
$ref: '#/components/schemas/InventoryPolicyEnum'
inventory_quantity:
type: integer
option1:
type: string
option2:
type: string
option3:
type: string
sku:
type: string
position:
type: integer
image_src:
type: string
weight:
type: number
format: double
weight_unit:
type: string
required:
- inventory_policy
- inventory_quantity
- option1
- price
ExternalProduct:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
shop:
allOf:
- $ref: '#/components/schemas/Shop'
readOnly: true
variants:
type: array
items:
$ref: '#/components/schemas/Variant'
readOnly: true
body_html:
type: string
nullable: true
maxLength: 60000
handle:
type: string
nullable: true
maxLength: 258
image_src:
type: string
nullable: true
maxLength: 1043
images:
type: array
items:
type: object
additionalProperties: {}
readOnly: true
options:
type: array
items:
type: object
additionalProperties: {}
description: Flatten option.values into a list of strings
readOnly: true
product_type:
type: string
nullable: true
maxLength: 1044
updated_at:
type: string
format: date-time
readOnly: true
published_at:
type: string
format: date-time
nullable: true
status:
$ref: '#/components/schemas/Status2eaEnum'
title:
type: string
# --- truncated at 32 KB (33 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/canal/refs/heads/main/openapi/canal-products-api-openapi.yml