Kanorio

API 參考

Products

Management API: GET /sites/{id}/products, POST /sites/{id}/products, GET /sites/{id}/products/{productId}, …

此頁只有英文版。API 參考、Webhook 事件及變更紀錄維持英文,與程式碼中的欄位名稱、錯誤碼一致。
Base URL https://app.kanorio.com/api/v1ErrorsPagination

List products

GET/sites/{id}/products
betastore:viewdefault (120/minute per token)

List products (ACTIVE first, then ARCHIVED; excludes sample template products by default unless includeTemplates=true) with images, variants and paid order counts; storeCurrency is the ISO 4217 code all amounts use. Errors: FORBIDDEN, INVALID_CURSOR.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • status"DRAFT" | "ACTIVE" | "ARCHIVED" · query
  • includeTemplatesboolean | "true" | "false" · query

    Include sample template products seeded for new stores (defaults to false).

  • limitinteger · query

    Maximum number of items to return, 1–100. Defaults to 20.

  • cursorstring · query

    Opaque cursor from the previous page's nextCursor. Omit for the first page.

Response 200

  • dataobject[]required
  • data[].idstringrequired
  • data[].titlestringrequired
  • data[].descriptionstring | nullrequired
  • data[].slugstring | nullrequired

    Last URL segment of the product page.

  • data[].status"DRAFT" | "ACTIVE" | "ARCHIVED"required

    DRAFT is not on the public shop. ACTIVE is published. ARCHIVED is retired.

  • data[].seoobjectrequired

    Search and share fields stored on the product.

  • data[].seo.titlestring | nullrequired
  • data[].seo.descriptionstring | nullrequired
  • data[].seo.keywordsstring[]required
  • data[].seo.ogTitlestring | nullrequired
  • data[].seo.ogDescriptionstring | nullrequired
  • data[].seo.ogImagestring | nullrequired

    Share image display URL. Changes with versions; do not store it.

  • data[].seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • data[].seo.canonicalUrlstring | nullrequired
  • data[].seo.robotsIndex"index" | "noindex"required
  • data[].seo.robotsFollow"follow" | "nofollow"required
  • data[].seo.excludeFromSiteSearchbooleanrequired

    Hide from visitor site search. Does not change robotsIndex.

  • data[].type"DIGITAL" | "PHYSICAL" | "SERVICE"required
  • data[].isTemplatebooleanrequired

    Sample product seeded for new sellers; not public.

  • data[].imagesobject[]required
  • data[].images[].assetIdstring | nullrequired

    assetId in the media library; null for older images that are not in it.

  • data[].images[].urlstringrequired

    Display URL (changes with versions; do not store it).

  • data[].images[].altstring
  • data[].images[].widthinteger
  • data[].images[].heightinteger
  • data[].imageFramingsobject | null[]

    Optional presentation framing per image (parallel to images; omitted when all images use automatic mode).

  • data[].imageFramings[].focusobject
  • data[].imageFramings[].screensobject
  • data[].imageFramings[].fitMode"contain" | "cover"
  • data[].imageFramings[].padColorstring
  • data[].purchaseNotesstring | nullrequired
  • data[].allowCustomAmountbooleanrequired
  • data[].reviewsEnabledbooleanrequired
  • data[].metadataobjectrequired

    Public integration fields (flat key/value, up to 50 keys, 16 KB). Visible to the storefront and Delivery API.

  • data[].privateMetadataobjectrequired

    Private integration fields; only the console, members and service accounts can read them.

  • data[].primaryCategoryIdstring | nullrequired
  • data[].optionsobject[]required
  • data[].options[].idstringrequired
  • data[].options[].namestringrequired
  • data[].options[].positionintegerrequired
  • data[].options[].valuesstring[]required
  • data[].pricingTiersobject[]required

    Purchasable variants; manage them in the console.

  • data[].pricingTiers[].idstringrequired
  • data[].pricingTiers[].titlestringrequired

    Variant title derived from option values (or the legacy name).

  • data[].pricingTiers[].optionValuesstring[]required
  • data[].pricingTiers[].amountintegerrequired

    Minor units in the store currency.

  • data[].pricingTiers[].compareAtAmountinteger | nullrequired
  • data[].pricingTiers[].isPublishedbooleanrequired
  • data[].pricingTiers[].sortOrderintegerrequired
  • data[].pricingTiers[].highlightBadgestring | nullrequired
  • data[].pricingTiers[].requiresShippingbooleanrequired

    Whether buyers of this variant enter a delivery address and pay shipping. Variants without their own setting follow productType, so one product can mix a course-only variant and a course + printed book variant. Set per variant in the console.

  • data[].pricingTiers[].accessDaysinteger | nullrequired

    Days buyers of this variant can access every deliverable it grants, counted from payment; null = permanent. One product can sell a 3-month variant and a lifetime variant. Set it with products.update({ pricingTiers: [{ id, accessDays }] }).

  • data[].deliverablesobject[]required

    Deliverables granted on purchase (any product type). tierId null = every variant. How long buyers keep access is pricingTiers[].accessDays. Manage with products.update({ deliverables }).

  • data[].deliverables[].deliverableIdstringrequired
  • data[].deliverables[].tierIdstring | nullrequired
  • data[].orderCountinteger

    Paid orders (list only).

  • data[].createdAtstringrequired
  • data[].updatedAtstringrequired
  • hasMorebooleanrequired

    True when another page exists; pass nextCursor to fetch it.

  • nextCursorstring | nullrequired

    Cursor for the next page, or null on the last page.

  • storeCurrencystringrequired

    Lowercase ISO 4217, e.g. twd, usd.

Errors

  • FORBIDDEN 403
  • INVALID_CURSOR 400

MCP tool products_list

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/products" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "data": [
    {
      "id": "prod_example01",
      "title": "Strawberry Birthday Cake",
      "description": "Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.",
      "slug": "strawberry-birthday-cake",
      "status": "ACTIVE",
      "seo": {
        "title": "Strawberry Birthday Cake",
        "description": "Seasonal strawberries and fresh whipped cream.",
        "keywords": [
          "cake",
          "birthday"
        ],
        "ogTitle": null,
        "ogDescription": null,
        "ogImage": null,
        "ogImageAssetId": null,
        "excludeFromSiteSearch": false,
        "canonicalUrl": null,
        "robotsIndex": "index",
        "robotsFollow": "follow"
      },
      "type": "PHYSICAL",
      "isTemplate": false,
      "images": [
        {
          "assetId": "asset_example01",
          "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
          "alt": "Strawberry birthday cake",
          "width": 2400,
          "height": 1600
        }
      ],
      "purchaseNotes": "Please leave your preferred pickup time in the order note.",
      "metadata": {},
      "privateMetadata": {},
      "allowCustomAmount": false,
      "reviewsEnabled": true,
      "primaryCategoryId": "pcat_example01",
      "options": [
        {
          "id": "opt_example01",
          "name": "Size",
          "position": 0,
          "values": [
            "6-inch",
            "8-inch"
          ]
        }
      ],
      "pricingTiers": [
        {
          "id": "tier_example01",
          "title": "6-inch",
          "optionValues": [
            "6-inch"
          ],
          "amount": 880,
          "compareAtAmount": null,
          "isPublished": true,
          "sortOrder": 0,
          "highlightBadge": null,
          "requiresShipping": true,
          "accessDays": null
        },
        {
          "id": "tier_example02",
          "title": "8-inch",
          "optionValues": [
            "8-inch"
          ],
          "amount": 1280,
          "compareAtAmount": null,
          "isPublished": true,
          "sortOrder": 1,
          "highlightBadge": null,
          "requiresShipping": true,
          "accessDays": null
        }
      ],
      "deliverables": [],
      "orderCount": 18,
      "createdAt": "2026-08-20T06:00:00.000Z",
      "updatedAt": "2026-10-06T08:00:00.000Z"
    }
  ],
  "storeCurrency": "TWD",
  "hasMore": false,
  "nextCursor": null
}

Create a product

POST/sites/{id}/products
betacommerce:managedefault (120/minute per token)

Create a DRAFT product. It stays off the public shop until products.publish. Add variants and prices in the console; a product with no published variant still cannot be purchased after it is published. detailMarkdown and faq are optional and render on the product detail page. Images and ogImageAssetId are media-library assets: pass their assetId (upload with media.upload or media.import_stock first). Slug is generated from the title when omitted. SEO fields are optional and only the ones you send are stored. productType only decides whether the product is shipped; link deliverables (courses, downloads) afterwards with products.update { deliverables } on either type. Errors: FORBIDDEN, VALIDATION (details.reason), SITE_SUSPENDED, ASSET_NOT_FOUND (details.assetIds: not in this site's media library, in the trash, or its file is missing), ASSET_NOT_ALLOWED (not an image, or a product file).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

Request body

  • titlestringrequired
  • descriptionstring

    Plain text description shown on the store card, checkout and product page. Optional; omit or send an empty string for none. Markdown markers are removed.

  • imagesobject[]required

    Up to 10; the first is the cover image. May be empty: the product page then renders without a gallery and listings show a placeholder.

  • images[].assetIdstringrequired

    assetId of an image in the media library (media.upload, media.import_stock, media.list).

  • images[].altstring
  • imageFramingsobject | null[]

    Optional framing per image (parallel to images; omit or pass null for automatic presentation).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | null
  • allowCustomAmountboolean
  • reviewsEnabledboolean
  • slugstring
  • productType"DIGITAL" | "PHYSICAL" | "SERVICE"

    Only about shipping, and only the default: DIGITAL (default) has nothing to ship, PHYSICAL is shipped and needs delivery settings. Each variant can override it (pricingTiers[].requiresShipping, set in the console). Either type can grant deliverables on purchase (products.update { deliverables }).

  • detailMarkdownstring | null

    Markdown shown under the product images on the detail page. Null or an empty string clears it. Omit on update to leave it unchanged.

  • faqobject[]

    On update, replaces the whole FAQ list. Omit to leave it unchanged. Pass [] to clear.

  • faq[].idstring
  • faq[].questionstringrequired
  • faq[].answerstringrequired

    Markdown subset, same as the FAQ module.

  • metadataobject | null

    Replace all public integration fields (flat key/value, up to 50 keys, 16 KB); null clears them.

  • privateMetadataobject | null

    Replace all private integration fields; null clears them.

  • seoTitlestring | null

    Search title. Null or empty clears it.

  • seoDescriptionstring | null
  • seoKeywordsstring[] | null

    Null or [] clears keywords.

  • ogImageAssetIdstring | null

    Share image assetId. Null removes it. Without one, an image may be generated automatically.

  • ogImageAltstring | null
  • ogImageFramingobject | null
  • ogImageFraming.focusobject
  • ogImageFraming.focus.xnumberrequired
  • ogImageFraming.focus.ynumberrequired
  • ogImageFraming.screensobject
  • ogImageFraming.screens.desktopobject
  • ogImageFraming.screens.tabletobject
  • ogImageFraming.screens.mobileobject
  • ogImageFraming.fitMode"contain" | "cover"
  • ogImageFraming.padColorstring
  • ogTitlestring | null
  • ogDescriptionstring | null
  • canonicalUrlstring | null
  • robotsIndex"index" | "noindex"
  • robotsFollow"follow" | "nofollow"
  • twitterCard"summary" | "summary_large_image"
  • autoOgEnabledboolean
  • excludeFromSiteSearchboolean

    Hide from visitor site search. Does not change robotsIndex.

Response 201

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • slugstring | nullrequired

    Last URL segment of the product page.

  • status"DRAFT" | "ACTIVE" | "ARCHIVED"required

    DRAFT is not on the public shop. ACTIVE is published. ARCHIVED is retired.

  • seoobjectrequired

    Search and share fields stored on the product.

  • seo.titlestring | nullrequired
  • seo.descriptionstring | nullrequired
  • seo.keywordsstring[]required
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL. Changes with versions; do not store it.

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndex"index" | "noindex"required
  • seo.robotsFollow"follow" | "nofollow"required
  • seo.excludeFromSiteSearchbooleanrequired

    Hide from visitor site search. Does not change robotsIndex.

  • type"DIGITAL" | "PHYSICAL" | "SERVICE"required
  • isTemplatebooleanrequired

    Sample product seeded for new sellers; not public.

  • imagesobject[]required
  • images[].assetIdstring | nullrequired

    assetId in the media library; null for older images that are not in it.

  • images[].urlstringrequired

    Display URL (changes with versions; do not store it).

  • images[].altstring
  • images[].widthinteger
  • images[].heightinteger
  • imageFramingsobject | null[]

    Optional presentation framing per image (parallel to images; omitted when all images use automatic mode).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | nullrequired
  • allowCustomAmountbooleanrequired
  • reviewsEnabledbooleanrequired
  • metadataobjectrequired

    Public integration fields (flat key/value, up to 50 keys, 16 KB). Visible to the storefront and Delivery API.

  • privateMetadataobjectrequired

    Private integration fields; only the console, members and service accounts can read them.

  • primaryCategoryIdstring | nullrequired
  • optionsobject[]required
  • options[].idstringrequired
  • options[].namestringrequired
  • options[].positionintegerrequired
  • options[].valuesstring[]required
  • pricingTiersobject[]required

    Purchasable variants; manage them in the console.

  • pricingTiers[].idstringrequired
  • pricingTiers[].titlestringrequired

    Variant title derived from option values (or the legacy name).

  • pricingTiers[].optionValuesstring[]required
  • pricingTiers[].amountintegerrequired

    Minor units in the store currency.

  • pricingTiers[].compareAtAmountinteger | nullrequired
  • pricingTiers[].isPublishedbooleanrequired
  • pricingTiers[].sortOrderintegerrequired
  • pricingTiers[].highlightBadgestring | nullrequired
  • pricingTiers[].requiresShippingbooleanrequired

    Whether buyers of this variant enter a delivery address and pay shipping. Variants without their own setting follow productType, so one product can mix a course-only variant and a course + printed book variant. Set per variant in the console.

  • pricingTiers[].accessDaysinteger | nullrequired

    Days buyers of this variant can access every deliverable it grants, counted from payment; null = permanent. One product can sell a 3-month variant and a lifetime variant. Set it with products.update({ pricingTiers: [{ id, accessDays }] }).

  • deliverablesobject[]required

    Deliverables granted on purchase (any product type). tierId null = every variant. How long buyers keep access is pricingTiers[].accessDays. Manage with products.update({ deliverables }).

  • deliverables[].deliverableIdstringrequired
  • deliverables[].tierIdstring | nullrequired
  • orderCountinteger

    Paid orders (list only).

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • VALIDATION 400 · details.reason
  • SITE_SUSPENDED 403
  • ASSET_NOT_FOUND 404 · details.assetIds: not in this site's media library, in the trash, or its file is missing
  • ASSET_NOT_ALLOWED 422 · not an image, or a product file

MCP tool products_create

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/products" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Strawberry Birthday Cake","productType":"PHYSICAL","description":"Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.","images":[{"assetId":"asset_example01","alt":"Strawberry birthday cake"}]}'
Response
{
  "id": "prod_example01",
  "title": "Strawberry Birthday Cake",
  "description": "Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.",
  "slug": "strawberry-birthday-cake",
  "status": "ACTIVE",
  "seo": {
    "title": "Strawberry Birthday Cake",
    "description": "Seasonal strawberries and fresh whipped cream.",
    "keywords": [
      "cake",
      "birthday"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "excludeFromSiteSearch": false,
    "canonicalUrl": null,
    "robotsIndex": "index",
    "robotsFollow": "follow"
  },
  "type": "PHYSICAL",
  "isTemplate": false,
  "images": [
    {
      "assetId": "asset_example01",
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "alt": "Strawberry birthday cake",
      "width": 2400,
      "height": 1600
    }
  ],
  "purchaseNotes": "Please leave your preferred pickup time in the order note.",
  "metadata": {},
  "privateMetadata": {},
  "allowCustomAmount": false,
  "reviewsEnabled": true,
  "primaryCategoryId": "pcat_example01",
  "options": [
    {
      "id": "opt_example01",
      "name": "Size",
      "position": 0,
      "values": [
        "6-inch",
        "8-inch"
      ]
    }
  ],
  "pricingTiers": [
    {
      "id": "tier_example01",
      "title": "6-inch",
      "optionValues": [
        "6-inch"
      ],
      "amount": 880,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 0,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    },
    {
      "id": "tier_example02",
      "title": "8-inch",
      "optionValues": [
        "8-inch"
      ],
      "amount": 1280,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 1,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    }
  ],
  "deliverables": [],
  "orderCount": 18,
  "createdAt": "2026-08-20T06:00:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Retrieve a product

GET/sites/{id}/products/{productId}
betastore:viewdefault (120/minute per token)

Get one product with images, options and variants. Errors: FORBIDDEN, PRODUCT_NOT_FOUND.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • productIdstring · pathrequired

    Product id. Get it from products.list.

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • slugstring | nullrequired

    Last URL segment of the product page.

  • status"DRAFT" | "ACTIVE" | "ARCHIVED"required

    DRAFT is not on the public shop. ACTIVE is published. ARCHIVED is retired.

  • seoobjectrequired

    Search and share fields stored on the product.

  • seo.titlestring | nullrequired
  • seo.descriptionstring | nullrequired
  • seo.keywordsstring[]required
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL. Changes with versions; do not store it.

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndex"index" | "noindex"required
  • seo.robotsFollow"follow" | "nofollow"required
  • seo.excludeFromSiteSearchbooleanrequired

    Hide from visitor site search. Does not change robotsIndex.

  • type"DIGITAL" | "PHYSICAL" | "SERVICE"required
  • isTemplatebooleanrequired

    Sample product seeded for new sellers; not public.

  • imagesobject[]required
  • images[].assetIdstring | nullrequired

    assetId in the media library; null for older images that are not in it.

  • images[].urlstringrequired

    Display URL (changes with versions; do not store it).

  • images[].altstring
  • images[].widthinteger
  • images[].heightinteger
  • imageFramingsobject | null[]

    Optional presentation framing per image (parallel to images; omitted when all images use automatic mode).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | nullrequired
  • allowCustomAmountbooleanrequired
  • reviewsEnabledbooleanrequired
  • metadataobjectrequired

    Public integration fields (flat key/value, up to 50 keys, 16 KB). Visible to the storefront and Delivery API.

  • privateMetadataobjectrequired

    Private integration fields; only the console, members and service accounts can read them.

  • primaryCategoryIdstring | nullrequired
  • optionsobject[]required
  • options[].idstringrequired
  • options[].namestringrequired
  • options[].positionintegerrequired
  • options[].valuesstring[]required
  • pricingTiersobject[]required

    Purchasable variants; manage them in the console.

  • pricingTiers[].idstringrequired
  • pricingTiers[].titlestringrequired

    Variant title derived from option values (or the legacy name).

  • pricingTiers[].optionValuesstring[]required
  • pricingTiers[].amountintegerrequired

    Minor units in the store currency.

  • pricingTiers[].compareAtAmountinteger | nullrequired
  • pricingTiers[].isPublishedbooleanrequired
  • pricingTiers[].sortOrderintegerrequired
  • pricingTiers[].highlightBadgestring | nullrequired
  • pricingTiers[].requiresShippingbooleanrequired

    Whether buyers of this variant enter a delivery address and pay shipping. Variants without their own setting follow productType, so one product can mix a course-only variant and a course + printed book variant. Set per variant in the console.

  • pricingTiers[].accessDaysinteger | nullrequired

    Days buyers of this variant can access every deliverable it grants, counted from payment; null = permanent. One product can sell a 3-month variant and a lifetime variant. Set it with products.update({ pricingTiers: [{ id, accessDays }] }).

  • deliverablesobject[]required

    Deliverables granted on purchase (any product type). tierId null = every variant. How long buyers keep access is pricingTiers[].accessDays. Manage with products.update({ deliverables }).

  • deliverables[].deliverableIdstringrequired
  • deliverables[].tierIdstring | nullrequired
  • orderCountinteger

    Paid orders (list only).

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PRODUCT_NOT_FOUND 404

MCP tool products_get

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/products/{productId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "id": "prod_example01",
  "title": "Strawberry Birthday Cake",
  "description": "Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.",
  "slug": "strawberry-birthday-cake",
  "status": "ACTIVE",
  "seo": {
    "title": "Strawberry Birthday Cake",
    "description": "Seasonal strawberries and fresh whipped cream.",
    "keywords": [
      "cake",
      "birthday"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "excludeFromSiteSearch": false,
    "canonicalUrl": null,
    "robotsIndex": "index",
    "robotsFollow": "follow"
  },
  "type": "PHYSICAL",
  "isTemplate": false,
  "images": [
    {
      "assetId": "asset_example01",
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "alt": "Strawberry birthday cake",
      "width": 2400,
      "height": 1600
    }
  ],
  "purchaseNotes": "Please leave your preferred pickup time in the order note.",
  "metadata": {},
  "privateMetadata": {},
  "allowCustomAmount": false,
  "reviewsEnabled": true,
  "primaryCategoryId": "pcat_example01",
  "options": [
    {
      "id": "opt_example01",
      "name": "Size",
      "position": 0,
      "values": [
        "6-inch",
        "8-inch"
      ]
    }
  ],
  "pricingTiers": [
    {
      "id": "tier_example01",
      "title": "6-inch",
      "optionValues": [
        "6-inch"
      ],
      "amount": 880,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 0,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    },
    {
      "id": "tier_example02",
      "title": "8-inch",
      "optionValues": [
        "8-inch"
      ],
      "amount": 1280,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 1,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    }
  ],
  "deliverables": [],
  "orderCount": 18,
  "createdAt": "2026-08-20T06:00:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Update a product

PATCH/sites/{id}/products/{productId}
betacommerce:managedefault (120/minute per token)

Partially update a product (only provided fields change; images replace the whole list). SEO fields are the same: omitted fields stay as they are, and null clears a text or share image. Publishing is products.publish: a DRAFT product stays off the shop. Changes to an ACTIVE product appear on the public store immediately. Errors: FORBIDDEN, PRODUCT_NOT_FOUND, VALIDATION (details.reason), SITE_SUSPENDED, ASSET_NOT_FOUND (details.assetIds: not in this site's media library, in the trash, or its file is missing), ASSET_NOT_ALLOWED (not an image, or a product file).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • productIdstring · pathrequired

    Product id. Get it from products.list.

Request body

  • titlestring
  • descriptionstring

    Plain text description shown on the store card, checkout and product page. Optional; omit or send an empty string for none. Markdown markers are removed.

  • imagesobject[]

    Up to 10; the first is the cover image. May be empty: the product page then renders without a gallery and listings show a placeholder.

  • images[].assetIdstringrequired

    assetId of an image in the media library (media.upload, media.import_stock, media.list).

  • images[].altstring
  • imageFramingsobject | null[]

    Optional framing per image (parallel to images; omit or pass null for automatic presentation).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | null
  • allowCustomAmountboolean
  • reviewsEnabledboolean
  • slugstring
  • productType"DIGITAL" | "PHYSICAL" | "SERVICE"

    Default shipping for variants without their own setting. Changing it affects future checkouts only; orders keep what was decided at checkout. Omit to leave it unchanged.

  • detailMarkdownstring | null

    Markdown shown under the product images on the detail page. Null or an empty string clears it. Omit on update to leave it unchanged.

  • faqobject[]

    On update, replaces the whole FAQ list. Omit to leave it unchanged. Pass [] to clear.

  • faq[].idstring
  • faq[].questionstringrequired
  • faq[].answerstringrequired

    Markdown subset, same as the FAQ module.

  • metadataobject | null

    Replace all public integration fields (flat key/value, up to 50 keys, 16 KB); null clears them.

  • privateMetadataobject | null

    Replace all private integration fields; null clears them.

  • seoTitlestring | null

    Search title. Null or empty clears it.

  • seoDescriptionstring | null
  • seoKeywordsstring[] | null

    Null or [] clears keywords.

  • ogImageAssetIdstring | null

    Share image assetId. Null removes it. Without one, an image may be generated automatically.

  • ogImageAltstring | null
  • ogImageFramingobject | null
  • ogImageFraming.focusobject
  • ogImageFraming.focus.xnumberrequired
  • ogImageFraming.focus.ynumberrequired
  • ogImageFraming.screensobject
  • ogImageFraming.screens.desktopobject
  • ogImageFraming.screens.tabletobject
  • ogImageFraming.screens.mobileobject
  • ogImageFraming.fitMode"contain" | "cover"
  • ogImageFraming.padColorstring
  • ogTitlestring | null
  • ogDescriptionstring | null
  • canonicalUrlstring | null
  • robotsIndex"index" | "noindex"
  • robotsFollow"follow" | "nofollow"
  • twitterCard"summary" | "summary_large_image"
  • autoOgEnabledboolean
  • excludeFromSiteSearchboolean

    Hide from visitor site search. Does not change robotsIndex.

  • deliverablesobject[]

    Replace the whole list of deliverables granted on purchase. Create deliverables first with deliverables.create. Pass [] to unlink all. Access duration is not set here: use pricingTiers[].accessDays.

  • deliverables[].deliverableIdstringrequired
  • deliverables[].tierIdstring | null
  • deliverables[].accessDaysany
  • pricingTiersobject[]

    Set access duration on existing variants by id: [{ id, accessDays }], accessDays null = permanent. It applies to every deliverable the variant grants. Only accessDays can be changed here; other variant fields are managed in the console. Variants not listed are left unchanged.

  • pricingTiers[].idstringrequired
  • pricingTiers[].accessDaysinteger | nullrequired

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • slugstring | nullrequired

    Last URL segment of the product page.

  • status"DRAFT" | "ACTIVE" | "ARCHIVED"required

    DRAFT is not on the public shop. ACTIVE is published. ARCHIVED is retired.

  • seoobjectrequired

    Search and share fields stored on the product.

  • seo.titlestring | nullrequired
  • seo.descriptionstring | nullrequired
  • seo.keywordsstring[]required
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL. Changes with versions; do not store it.

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndex"index" | "noindex"required
  • seo.robotsFollow"follow" | "nofollow"required
  • seo.excludeFromSiteSearchbooleanrequired

    Hide from visitor site search. Does not change robotsIndex.

  • type"DIGITAL" | "PHYSICAL" | "SERVICE"required
  • isTemplatebooleanrequired

    Sample product seeded for new sellers; not public.

  • imagesobject[]required
  • images[].assetIdstring | nullrequired

    assetId in the media library; null for older images that are not in it.

  • images[].urlstringrequired

    Display URL (changes with versions; do not store it).

  • images[].altstring
  • images[].widthinteger
  • images[].heightinteger
  • imageFramingsobject | null[]

    Optional presentation framing per image (parallel to images; omitted when all images use automatic mode).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | nullrequired
  • allowCustomAmountbooleanrequired
  • reviewsEnabledbooleanrequired
  • metadataobjectrequired

    Public integration fields (flat key/value, up to 50 keys, 16 KB). Visible to the storefront and Delivery API.

  • privateMetadataobjectrequired

    Private integration fields; only the console, members and service accounts can read them.

  • primaryCategoryIdstring | nullrequired
  • optionsobject[]required
  • options[].idstringrequired
  • options[].namestringrequired
  • options[].positionintegerrequired
  • options[].valuesstring[]required
  • pricingTiersobject[]required

    Purchasable variants; manage them in the console.

  • pricingTiers[].idstringrequired
  • pricingTiers[].titlestringrequired

    Variant title derived from option values (or the legacy name).

  • pricingTiers[].optionValuesstring[]required
  • pricingTiers[].amountintegerrequired

    Minor units in the store currency.

  • pricingTiers[].compareAtAmountinteger | nullrequired
  • pricingTiers[].isPublishedbooleanrequired
  • pricingTiers[].sortOrderintegerrequired
  • pricingTiers[].highlightBadgestring | nullrequired
  • pricingTiers[].requiresShippingbooleanrequired

    Whether buyers of this variant enter a delivery address and pay shipping. Variants without their own setting follow productType, so one product can mix a course-only variant and a course + printed book variant. Set per variant in the console.

  • pricingTiers[].accessDaysinteger | nullrequired

    Days buyers of this variant can access every deliverable it grants, counted from payment; null = permanent. One product can sell a 3-month variant and a lifetime variant. Set it with products.update({ pricingTiers: [{ id, accessDays }] }).

  • deliverablesobject[]required

    Deliverables granted on purchase (any product type). tierId null = every variant. How long buyers keep access is pricingTiers[].accessDays. Manage with products.update({ deliverables }).

  • deliverables[].deliverableIdstringrequired
  • deliverables[].tierIdstring | nullrequired
  • orderCountinteger

    Paid orders (list only).

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PRODUCT_NOT_FOUND 404
  • VALIDATION 400 · details.reason
  • SITE_SUSPENDED 403
  • ASSET_NOT_FOUND 404 · details.assetIds: not in this site's media library, in the trash, or its file is missing
  • ASSET_NOT_ALLOWED 422 · not an image, or a product file

MCP tool products_update

curl -X PATCH "https://app.kanorio.com/api/v1/sites/{id}/products/{productId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"purchaseNotes":"Please leave your preferred pickup time in the order note."}'
Response
{
  "id": "prod_example01",
  "title": "Strawberry Birthday Cake",
  "description": "Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.",
  "slug": "strawberry-birthday-cake",
  "status": "ACTIVE",
  "seo": {
    "title": "Strawberry Birthday Cake",
    "description": "Seasonal strawberries and fresh whipped cream.",
    "keywords": [
      "cake",
      "birthday"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "excludeFromSiteSearch": false,
    "canonicalUrl": null,
    "robotsIndex": "index",
    "robotsFollow": "follow"
  },
  "type": "PHYSICAL",
  "isTemplate": false,
  "images": [
    {
      "assetId": "asset_example01",
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "alt": "Strawberry birthday cake",
      "width": 2400,
      "height": 1600
    }
  ],
  "purchaseNotes": "Please leave your preferred pickup time in the order note.",
  "metadata": {},
  "privateMetadata": {},
  "allowCustomAmount": false,
  "reviewsEnabled": true,
  "primaryCategoryId": "pcat_example01",
  "options": [
    {
      "id": "opt_example01",
      "name": "Size",
      "position": 0,
      "values": [
        "6-inch",
        "8-inch"
      ]
    }
  ],
  "pricingTiers": [
    {
      "id": "tier_example01",
      "title": "6-inch",
      "optionValues": [
        "6-inch"
      ],
      "amount": 880,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 0,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    },
    {
      "id": "tier_example02",
      "title": "8-inch",
      "optionValues": [
        "8-inch"
      ],
      "amount": 1280,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 1,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    }
  ],
  "deliverables": [],
  "orderCount": 18,
  "createdAt": "2026-08-20T06:00:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Publish a product

POST/sites/{id}/products/{productId}/publish
betacommerce:managepublish (30/hour per token)

Publish a product (status ACTIVE) so it appears on the public shop and its detail page. Sample products and archived products cannot be published. Idempotent when already ACTIVE. Errors: FORBIDDEN, PRODUCT_NOT_FOUND, PRODUCT_NOT_LISTABLE, SITE_SUSPENDED.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • productIdstring · pathrequired

    Product id. Get it from products.list.

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • slugstring | nullrequired

    Last URL segment of the product page.

  • status"DRAFT" | "ACTIVE" | "ARCHIVED"required

    DRAFT is not on the public shop. ACTIVE is published. ARCHIVED is retired.

  • seoobjectrequired

    Search and share fields stored on the product.

  • seo.titlestring | nullrequired
  • seo.descriptionstring | nullrequired
  • seo.keywordsstring[]required
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL. Changes with versions; do not store it.

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndex"index" | "noindex"required
  • seo.robotsFollow"follow" | "nofollow"required
  • seo.excludeFromSiteSearchbooleanrequired

    Hide from visitor site search. Does not change robotsIndex.

  • type"DIGITAL" | "PHYSICAL" | "SERVICE"required
  • isTemplatebooleanrequired

    Sample product seeded for new sellers; not public.

  • imagesobject[]required
  • images[].assetIdstring | nullrequired

    assetId in the media library; null for older images that are not in it.

  • images[].urlstringrequired

    Display URL (changes with versions; do not store it).

  • images[].altstring
  • images[].widthinteger
  • images[].heightinteger
  • imageFramingsobject | null[]

    Optional presentation framing per image (parallel to images; omitted when all images use automatic mode).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | nullrequired
  • allowCustomAmountbooleanrequired
  • reviewsEnabledbooleanrequired
  • metadataobjectrequired

    Public integration fields (flat key/value, up to 50 keys, 16 KB). Visible to the storefront and Delivery API.

  • privateMetadataobjectrequired

    Private integration fields; only the console, members and service accounts can read them.

  • primaryCategoryIdstring | nullrequired
  • optionsobject[]required
  • options[].idstringrequired
  • options[].namestringrequired
  • options[].positionintegerrequired
  • options[].valuesstring[]required
  • pricingTiersobject[]required

    Purchasable variants; manage them in the console.

  • pricingTiers[].idstringrequired
  • pricingTiers[].titlestringrequired

    Variant title derived from option values (or the legacy name).

  • pricingTiers[].optionValuesstring[]required
  • pricingTiers[].amountintegerrequired

    Minor units in the store currency.

  • pricingTiers[].compareAtAmountinteger | nullrequired
  • pricingTiers[].isPublishedbooleanrequired
  • pricingTiers[].sortOrderintegerrequired
  • pricingTiers[].highlightBadgestring | nullrequired
  • pricingTiers[].requiresShippingbooleanrequired

    Whether buyers of this variant enter a delivery address and pay shipping. Variants without their own setting follow productType, so one product can mix a course-only variant and a course + printed book variant. Set per variant in the console.

  • pricingTiers[].accessDaysinteger | nullrequired

    Days buyers of this variant can access every deliverable it grants, counted from payment; null = permanent. One product can sell a 3-month variant and a lifetime variant. Set it with products.update({ pricingTiers: [{ id, accessDays }] }).

  • deliverablesobject[]required

    Deliverables granted on purchase (any product type). tierId null = every variant. How long buyers keep access is pricingTiers[].accessDays. Manage with products.update({ deliverables }).

  • deliverables[].deliverableIdstringrequired
  • deliverables[].tierIdstring | nullrequired
  • orderCountinteger

    Paid orders (list only).

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PRODUCT_NOT_FOUND 404
  • PRODUCT_NOT_LISTABLE 422
  • SITE_SUSPENDED 403

MCP tool products_publish

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/products/{productId}/publish" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "prod_example01",
  "title": "Strawberry Birthday Cake",
  "description": "Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.",
  "slug": "strawberry-birthday-cake",
  "status": "ACTIVE",
  "seo": {
    "title": "Strawberry Birthday Cake",
    "description": "Seasonal strawberries and fresh whipped cream.",
    "keywords": [
      "cake",
      "birthday"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "excludeFromSiteSearch": false,
    "canonicalUrl": null,
    "robotsIndex": "index",
    "robotsFollow": "follow"
  },
  "type": "PHYSICAL",
  "isTemplate": false,
  "images": [
    {
      "assetId": "asset_example01",
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "alt": "Strawberry birthday cake",
      "width": 2400,
      "height": 1600
    }
  ],
  "purchaseNotes": "Please leave your preferred pickup time in the order note.",
  "metadata": {},
  "privateMetadata": {},
  "allowCustomAmount": false,
  "reviewsEnabled": true,
  "primaryCategoryId": "pcat_example01",
  "options": [
    {
      "id": "opt_example01",
      "name": "Size",
      "position": 0,
      "values": [
        "6-inch",
        "8-inch"
      ]
    }
  ],
  "pricingTiers": [
    {
      "id": "tier_example01",
      "title": "6-inch",
      "optionValues": [
        "6-inch"
      ],
      "amount": 880,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 0,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    },
    {
      "id": "tier_example02",
      "title": "8-inch",
      "optionValues": [
        "8-inch"
      ],
      "amount": 1280,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 1,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    }
  ],
  "deliverables": [],
  "orderCount": 18,
  "createdAt": "2026-08-20T06:00:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Unpublish a product

POST/sites/{id}/products/{productId}/unpublish
betacommerce:managepublish (30/hour per token)

Unpublish a product (status DRAFT). It leaves the public shop and its detail page returns not found. Sample products and archived products cannot be unpublished; restore an archived product in the console first. Idempotent when already DRAFT. Errors: FORBIDDEN, PRODUCT_NOT_FOUND, PRODUCT_NOT_LISTABLE, SITE_SUSPENDED.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • productIdstring · pathrequired

    Product id. Get it from products.list.

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • slugstring | nullrequired

    Last URL segment of the product page.

  • status"DRAFT" | "ACTIVE" | "ARCHIVED"required

    DRAFT is not on the public shop. ACTIVE is published. ARCHIVED is retired.

  • seoobjectrequired

    Search and share fields stored on the product.

  • seo.titlestring | nullrequired
  • seo.descriptionstring | nullrequired
  • seo.keywordsstring[]required
  • seo.ogTitlestring | nullrequired
  • seo.ogDescriptionstring | nullrequired
  • seo.ogImagestring | nullrequired

    Share image display URL. Changes with versions; do not store it.

  • seo.ogImageAssetIdstring | nullrequired

    assetId of the share image when it is in the media library.

  • seo.canonicalUrlstring | nullrequired
  • seo.robotsIndex"index" | "noindex"required
  • seo.robotsFollow"follow" | "nofollow"required
  • seo.excludeFromSiteSearchbooleanrequired

    Hide from visitor site search. Does not change robotsIndex.

  • type"DIGITAL" | "PHYSICAL" | "SERVICE"required
  • isTemplatebooleanrequired

    Sample product seeded for new sellers; not public.

  • imagesobject[]required
  • images[].assetIdstring | nullrequired

    assetId in the media library; null for older images that are not in it.

  • images[].urlstringrequired

    Display URL (changes with versions; do not store it).

  • images[].altstring
  • images[].widthinteger
  • images[].heightinteger
  • imageFramingsobject | null[]

    Optional presentation framing per image (parallel to images; omitted when all images use automatic mode).

  • imageFramings[].focusobject
  • imageFramings[].focus.xnumberrequired
  • imageFramings[].focus.ynumberrequired
  • imageFramings[].screensobject
  • imageFramings[].screens.desktopobject
  • imageFramings[].screens.tabletobject
  • imageFramings[].screens.mobileobject
  • imageFramings[].fitMode"contain" | "cover"
  • imageFramings[].padColorstring
  • purchaseNotesstring | nullrequired
  • allowCustomAmountbooleanrequired
  • reviewsEnabledbooleanrequired
  • metadataobjectrequired

    Public integration fields (flat key/value, up to 50 keys, 16 KB). Visible to the storefront and Delivery API.

  • privateMetadataobjectrequired

    Private integration fields; only the console, members and service accounts can read them.

  • primaryCategoryIdstring | nullrequired
  • optionsobject[]required
  • options[].idstringrequired
  • options[].namestringrequired
  • options[].positionintegerrequired
  • options[].valuesstring[]required
  • pricingTiersobject[]required

    Purchasable variants; manage them in the console.

  • pricingTiers[].idstringrequired
  • pricingTiers[].titlestringrequired

    Variant title derived from option values (or the legacy name).

  • pricingTiers[].optionValuesstring[]required
  • pricingTiers[].amountintegerrequired

    Minor units in the store currency.

  • pricingTiers[].compareAtAmountinteger | nullrequired
  • pricingTiers[].isPublishedbooleanrequired
  • pricingTiers[].sortOrderintegerrequired
  • pricingTiers[].highlightBadgestring | nullrequired
  • pricingTiers[].requiresShippingbooleanrequired

    Whether buyers of this variant enter a delivery address and pay shipping. Variants without their own setting follow productType, so one product can mix a course-only variant and a course + printed book variant. Set per variant in the console.

  • pricingTiers[].accessDaysinteger | nullrequired

    Days buyers of this variant can access every deliverable it grants, counted from payment; null = permanent. One product can sell a 3-month variant and a lifetime variant. Set it with products.update({ pricingTiers: [{ id, accessDays }] }).

  • deliverablesobject[]required

    Deliverables granted on purchase (any product type). tierId null = every variant. How long buyers keep access is pricingTiers[].accessDays. Manage with products.update({ deliverables }).

  • deliverables[].deliverableIdstringrequired
  • deliverables[].tierIdstring | nullrequired
  • orderCountinteger

    Paid orders (list only).

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PRODUCT_NOT_FOUND 404
  • PRODUCT_NOT_LISTABLE 422
  • SITE_SUSPENDED 403

MCP tool products_unpublish

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/products/{productId}/unpublish" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "prod_example01",
  "title": "Strawberry Birthday Cake",
  "description": "Seasonal strawberries and fresh whipped cream. Pre-order at least one day ahead.",
  "slug": "strawberry-birthday-cake",
  "status": "ACTIVE",
  "seo": {
    "title": "Strawberry Birthday Cake",
    "description": "Seasonal strawberries and fresh whipped cream.",
    "keywords": [
      "cake",
      "birthday"
    ],
    "ogTitle": null,
    "ogDescription": null,
    "ogImage": null,
    "ogImageAssetId": null,
    "excludeFromSiteSearch": false,
    "canonicalUrl": null,
    "robotsIndex": "index",
    "robotsFollow": "follow"
  },
  "type": "PHYSICAL",
  "isTemplate": false,
  "images": [
    {
      "assetId": "asset_example01",
      "url": "https://media.kanorio.com/example/sunny-bakery-hero.jpg",
      "alt": "Strawberry birthday cake",
      "width": 2400,
      "height": 1600
    }
  ],
  "purchaseNotes": "Please leave your preferred pickup time in the order note.",
  "metadata": {},
  "privateMetadata": {},
  "allowCustomAmount": false,
  "reviewsEnabled": true,
  "primaryCategoryId": "pcat_example01",
  "options": [
    {
      "id": "opt_example01",
      "name": "Size",
      "position": 0,
      "values": [
        "6-inch",
        "8-inch"
      ]
    }
  ],
  "pricingTiers": [
    {
      "id": "tier_example01",
      "title": "6-inch",
      "optionValues": [
        "6-inch"
      ],
      "amount": 880,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 0,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    },
    {
      "id": "tier_example02",
      "title": "8-inch",
      "optionValues": [
        "8-inch"
      ],
      "amount": 1280,
      "compareAtAmount": null,
      "isPublished": true,
      "sortOrder": 1,
      "highlightBadge": null,
      "requiresShipping": true,
      "accessDays": null
    }
  ],
  "deliverables": [],
  "orderCount": 18,
  "createdAt": "2026-08-20T06:00:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Archive a product

POST/sites/{id}/products/{productId}/archive
betacommerce:managedefault (120/minute per token)

Archive a product: it disappears from the store but keeps its orders and can be restored in the console. Deleting products is not available to agents. Errors: FORBIDDEN, PRODUCT_NOT_FOUND, SITE_SUSPENDED.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • productIdstring · pathrequired

    Product id. Get it from products.list.

Response 200

  • idstringrequired
  • status"ARCHIVED"required

Errors

  • FORBIDDEN 403
  • PRODUCT_NOT_FOUND 404
  • SITE_SUSPENDED 403

MCP tool products_archive

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/products/{productId}/archive" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "prod_example01",
  "status": "ARCHIVED"
}