Canal products API
The products API from Canal — 5 operation(s) for products.
The products API from Canal — 5 operation(s) for products.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/canal-products-api"
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
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:
Shop:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
email:
type:
- string
- 'null'
readOnly: true
phone:
type:
- string
- 'null'
maxLength: 128
name:
type: string
maxLength: 129
description:
type:
- string
- 'null'
maxLength: 6144
myshopify_domain:
type: string
maxLength: 128
province:
type:
- string
- 'null'
maxLength: 122
country:
type: string
maxLength: 64
domain:
type:
- string
- 'null'
maxLength: 128
display_domain:
type:
- string
- 'null'
readOnly: true
privacy_policy_url:
type:
- string
- 'null'
format: uri
maxLength: 500
terms_of_service_url:
type:
- string
- 'null'
format: uri
maxLength: 500
required:
- country
- display_domain
- email
- id
- myshopify_domain
- name
PaginatedExternalProductList:
type: object
required:
- results
properties:
next:
type:
- string
- 'null'
format: uri
example: http://api.example.org/accounts/?cursor=cD00ODY%3D"
previous:
type:
- string
- 'null'
format: uri
example: http://api.example.org/accounts/?cursor=cj0xJnA9NDg3
results:
type: array
items:
$ref: '#/components/schemas/ExternalProduct'
Status2eaEnum:
enum:
- active
- draft
- archived
- unlisted
type: string
description: '* `active` - active
* `draft` - draft
* `archived` - archived
* `unlisted` - unlisted'
ResyncShopkeepProduct:
type: object
properties:
fields_to_resync:
type: array
items:
$ref: '#/components/schemas/FieldsToResyncEnum'
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
- 'null'
format: decimal
pattern: ^-?\d{0,10}(?:\.\d{0,2})?$
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
Image:
type: object
properties:
id:
type: string
position:
type: integer
src:
type: string
format: uri
display_src:
type:
- string
- 'null'
format: uri
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
- 'null'
format: uuid
required:
- canal_variant_ids
- src
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
- 'null'
maxLength: 60000
handle:
type:
- string
- 'null'
maxLength: 258
image_src:
type:
- string
- 'null'
maxLength: 1043
images:
type: array
items:
$ref: '#/components/schemas/Image'
options: {}
product_type:
type:
- string
- 'null'
maxLength: 1044
updated_at:
type: string
format: date-time
readOnly: true
published_at:
type:
- string
- 'null'
format: date-time
status:
$ref: '#/components/schemas/Status2eaEnum'
title:
type: string
maxLength: 1029
vendor:
type:
- string
- 'null'
maxLength: 227
tags:
type:
- string
- 'null'
maxLength: 63750
permalink:
type:
- string
- 'null'
format: uri
maxLength: 2000
number_of_reviews:
type:
- integer
- 'null'
maximum: 2147483647
minimum: -2147483648
star_rating:
type:
- number
- 'null'
format: double
required:
- id
- shop
- title
- updated_at
- variants
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
- 'null'
maxLength: 60000
handle:
type:
- string
- 'null'
maxLength: 258
image_src:
type:
- string
- 'null'
maxLength: 1043
images:
type: array
items:
$ref: '#/components/schemas/Image'
options: {}
product_type:
type:
- string
- 'null'
maxLength: 1044
updated_at:
type: string
format: date-time
readOnly: true
published_at:
type:
- string
- 'null'
format: date-time
status:
$ref: '#/components/schemas/Status2eaEnum'
title:
type: string
maxLength: 1029
vendor:
type:
- string
- 'null'
maxLength: 227
tags:
type:
- string
- 'null'
maxLength: 63750
permalink:
type:
- string
- 'null'
format: uri
maxLength: 2000
number_of_reviews:
type:
- integer
- 'null'
maximum: 2147483647
minimum: -2147483648
star_rating:
type:
- number
- 'null'
format: double
Error:
type: object
properties:
message:
type: string
detail: {}
InventoryPolicyEnum:
enum:
- continue
- deny
type: string
description: '* `continue` - continue
* `deny` - deny'
Variant:
type: object
properties:
id:
type: string
format: uuid
readOnly: true
shop:
allOf:
- $ref: '#/components/schemas/Shop'
readOnly: true
inventory_policy:
type:
- string
- 'null'
maxLength: 123
inventory_quantity:
type:
- integer
- 'null'
maximum: 2147483647
minimum: -2147483648
inventory_item_cost:
type: number
format: double
option1:
type:
- string
- 'null'
maxLength: 255
option2:
type:
- string
- 'null'
maxLength: 256
option3:
type:
- string
- 'null'
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
- 'null'
maxLength: 128
origin_supplier_currency:
type:
- string
- 'null'
readOnly: true
title:
type: string
sku:
type:
- string
- 'null'
readOnly: true
upc:
type:
- string
- 'null'
maxLength: 253
grams:
type:
- number
- 'null'
format: double
weight:
type:
- number
- 'null'
format: double
weight_unit:
type:
- string
- 'null'
maxLength: 3
pause_selling:
type: boolean
origin_supplier_id:
type:
- string
- 'null'
readOnly: true
origin_supplier_name:
type:
- string
- 'null'
readOnly: true
available_for_ordering:
type: boolean
readOnly: true
supplier_sku:
type:
- string
- 'null'
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
- 'null'
description: The connected supplier variant's price, sourced from the supplier directly.
readOnly: true
sup_compare_at_price:
type:
- string
- 'null'
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
ResyncShopkeepProductResponse:
type: object
properties:
ok:
type: boolean
status:
type:
- string
- 'null'
shopify_product:
allOf:
- $ref: '#/components/schemas/Product'
required:
- ok
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
- 'null'
maxLength: 60000
handle:
type:
- string
- 'null'
maxLength: 258
image_src:
type:
- string
- 'null'
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
- 'null'
maxLength: 1044
updated_at:
type: string
format: date-time
readOnly: true
published_at:
type:
- string
- 'null'
format: date-time
status:
$ref: '#/components/schemas/Status2eaEnum'
title:
type: string
maxLength: 1029
vendor:
type:
- string
- 'null'
maxLength: 227
tags:
type:
- string
- 'null'
maxLength: 63750
permalink:
type:
- string
- 'null'
format: uri
maxLength: 2000
number_of_reviews:
type:
- integer
- 'null'
maximum: 2147483647
minimum: -2147483648
star_rating:
type:
- number
- 'null'
format: double
product_type_category:
type:
- string
- 'null'
description: Get Shoppable Ads product type category breadcrumb path if available.
readOnly: true
customer_charge_amount:
type:
- object
- 'null'
additionalProperties: {}
readOnly: true
required:
- customer_charge_amount
- id
- images
- options
- product_type_category
- shop
- title
- updated_at
- variants
PushProduct:
type: object
properties:
title:
type: string
body_html:
type: string
variants:
type: array
items:
$ref: '#/components/schemas/PushProductVariant'
# --- 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