Kanorio

API 参考

Promotions

Management API: GET /sites/{id}/promotions, POST /sites/{id}/promotions, GET /sites/{id}/promotions/{promotionId}, …

本页只有英文版。API 参考、Webhook 事件和更新日志保持英文,与代码中的字段名称、错误码一致。
Base URL https://app.kanorio.com/api/v1ErrorsPagination

List promotions

GET/sites/{id}/promotions
betamarketing:viewdefault (120/minute per token)

List promotions (automatic discounts and discount codes), newest first. Archived promotions are left out unless includeArchived is true. Errors: FORBIDDEN, INVALID_CURSOR.

Parameters

  • idstring · pathrequired

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

  • includeArchivedboolean · query

    Also return archived promotions.

  • 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[].namestringrequired

    Shown to the seller and, for automatic promotions, as the line on the checkout page.

  • data[].kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    Wizard type; drives the storefront badge and which conditions apply.

  • data[].method"CODE" | "AUTOMATIC"required

    CODE = the buyer enters a code at checkout; AUTOMATIC = applied when conditions match.

  • data[].discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required

    PERCENTAGE of the matching lines, FIXED_AMOUNT off the order once, or OVERRIDE_PRICE as the per-unit price of matching lines.

  • data[].codestring | nullrequired

    Discount code (uppercase) when method is CODE.

  • data[].percentageinteger | nullrequired

    1–100 when discountType is PERCENTAGE.

  • data[].amountsobject[]required

    Per-currency amount for FIXED_AMOUNT / OVERRIDE_PRICE.

  • data[].amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • data[].amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • data[].minQuantityinteger | nullrequired

    Minimum quantity across matching lines.

  • data[].minOrderAmountinteger | nullrequired

    Minimum discountable subtotal of the order, minor units.

  • data[].startsAtstring | nullrequired

    ISO 8601 start; null = already started.

  • data[].endsAtstring | nullrequired

    ISO 8601 end; null = no end. Required for FLASH_SALE.

  • data[].dailyStartMinuteinteger | nullrequired

    Daily window start, minutes from midnight in the site timezone.

  • data[].dailyEndMinuteinteger | nullrequired

    Daily window end, minutes from midnight in the site timezone.

  • data[].usageLimitinteger | nullrequired

    Total paid orders allowed; null = unlimited.

  • data[].perCustomerLimitinteger | nullrequired

    Paid orders per customer; null = unlimited.

  • data[].usageCountintegerrequired

    Paid orders that redeemed this promotion (refunds are not subtracted).

  • data[].selectorobject | nullrequired
  • data[].selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • data[].selector.refsobject[]
  • data[].selector.categoryIdsstring[]
  • data[].selector.tagsstring[]
  • data[].selector.priceRangeobject
  • data[].marketIdsstring[]required

    Only these markets; empty = every market.

  • data[].audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"required

    FIRST_PURCHASE = no paid order yet; RETURNING = at least minPriorPurchases paid orders.

  • data[].minPriorPurchasesinteger | nullrequired

    RETURNING threshold; null = 1.

  • data[].badgeOverridestring | nullrequired

    Custom storefront badge text (automatic promotions only).

  • data[].isActivebooleanrequired
  • data[].archivedAtstring | nullrequired

    Archived promotions are hidden from the dashboard list and never apply.

  • 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.

Errors

  • FORBIDDEN 403
  • INVALID_CURSOR 400

MCP tool promotions_list

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/promotions" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "data": [
    {
      "id": "prm_example01",
      "name": "Autumn 10% Off",
      "kind": "DISCOUNT_CODE",
      "method": "CODE",
      "discountType": "PERCENTAGE",
      "code": "AUTUMN10",
      "percentage": 10,
      "amounts": [],
      "minQuantity": null,
      "minOrderAmount": null,
      "startsAt": "2026-10-01T02:30:00.000Z",
      "endsAt": null,
      "dailyStartMinute": null,
      "dailyEndMinute": null,
      "usageLimit": 100,
      "perCustomerLimit": 1,
      "usageCount": 14,
      "selector": null,
      "marketIds": [],
      "audienceType": "ALL",
      "minPriorPurchases": null,
      "badgeOverride": null,
      "isActive": true,
      "archivedAt": null,
      "createdAt": "2026-10-01T02:30:00.000Z",
      "updatedAt": "2026-10-06T08:00:00.000Z"
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

Create a promotion

POST/sites/{id}/promotions
betamarketing:managedefault (120/minute per token)Idempotency-Key

Create a promotion. It applies at Kanorio's hosted checkout only; a headless storefront can read it to show badges but cannot apply it. Same rules as the dashboard (code uniqueness, FLASH_SALE needs endsAt, selector references must belong to this site). Errors: FORBIDDEN, VALIDATION (details.code: CODE_REQUIRED, KIND_METHOD_MISMATCH, SCOPE_REQUIRED, START_MUST_BE_BEFORE_END, FLASH_SALE_ENDS_AT_REQUIRED, DAILY_WINDOW_INCOMPLETE, INVALID_PRODUCT, INVALID_VARIANT, INVALID_CATEGORY, INVALID_RESOURCE, INVALID_MARKET, UNSUPPORTED_LINE_KIND, TAGS_NOT_SUPPORTED), PROMOTION_CODE_CONFLICT, SITE_SUSPENDED.

Parameters

  • idstring · pathrequired

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

  • Idempotency-Keystring · header

    Client-chosen key (1-200 chars). Retrying with the same key and the same body returns the original result; the same key with a different body is rejected with IDEMPOTENCY_CONFLICT (409). Keys expire after 24 hours.

Request body

  • namestringrequired
  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    DISCOUNT_CODE must use method CODE; the other kinds use AUTOMATIC.

  • method"CODE" | "AUTOMATIC"required
  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required
  • codestring

    Required when method is CODE; stored uppercase; unique per site.

  • percentageinteger
  • amountsobject[]

    Required for FIXED_AMOUNT / OVERRIDE_PRICE; one entry per currency.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger
  • minOrderAmountinteger

    Minor units.

  • startsAtstring

    ISO 8601 with offset.

  • endsAtstring

    ISO 8601 with offset; required for FLASH_SALE.

  • dailyStartMinuteinteger
  • dailyEndMinuteinteger

    Must be set together with dailyStartMinute.

  • usageLimitinteger
  • perCustomerLimitinteger
  • selectorobject | null
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]

    Market ids of this site; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"
  • minPriorPurchasesinteger

    Only with audienceType RETURNING.

  • badgeOverridestring
  • isActiveboolean

    Default true on create.

Response 200

  • idstringrequired
  • namestringrequired

    Shown to the seller and, for automatic promotions, as the line on the checkout page.

  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    Wizard type; drives the storefront badge and which conditions apply.

  • method"CODE" | "AUTOMATIC"required

    CODE = the buyer enters a code at checkout; AUTOMATIC = applied when conditions match.

  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required

    PERCENTAGE of the matching lines, FIXED_AMOUNT off the order once, or OVERRIDE_PRICE as the per-unit price of matching lines.

  • codestring | nullrequired

    Discount code (uppercase) when method is CODE.

  • percentageinteger | nullrequired

    1–100 when discountType is PERCENTAGE.

  • amountsobject[]required

    Per-currency amount for FIXED_AMOUNT / OVERRIDE_PRICE.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger | nullrequired

    Minimum quantity across matching lines.

  • minOrderAmountinteger | nullrequired

    Minimum discountable subtotal of the order, minor units.

  • startsAtstring | nullrequired

    ISO 8601 start; null = already started.

  • endsAtstring | nullrequired

    ISO 8601 end; null = no end. Required for FLASH_SALE.

  • dailyStartMinuteinteger | nullrequired

    Daily window start, minutes from midnight in the site timezone.

  • dailyEndMinuteinteger | nullrequired

    Daily window end, minutes from midnight in the site timezone.

  • usageLimitinteger | nullrequired

    Total paid orders allowed; null = unlimited.

  • perCustomerLimitinteger | nullrequired

    Paid orders per customer; null = unlimited.

  • usageCountintegerrequired

    Paid orders that redeemed this promotion (refunds are not subtracted).

  • selectorobject | nullrequired
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]required

    Only these markets; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"required

    FIRST_PURCHASE = no paid order yet; RETURNING = at least minPriorPurchases paid orders.

  • minPriorPurchasesinteger | nullrequired

    RETURNING threshold; null = 1.

  • badgeOverridestring | nullrequired

    Custom storefront badge text (automatic promotions only).

  • isActivebooleanrequired
  • archivedAtstring | nullrequired

    Archived promotions are hidden from the dashboard list and never apply.

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • VALIDATION 400 · details.code: CODE_REQUIRED, KIND_METHOD_MISMATCH, SCOPE_REQUIRED, START_MUST_BE_BEFORE_END, FLASH_SALE_ENDS_AT_REQUIRED, DAILY_WINDOW_INCOMPLETE, INVALID_PRODUCT, INVALID_VARIANT, INVALID_CATEGORY, INVALID_RESOURCE, INVALID_MARKET, UNSUPPORTED_LINE_KIND, TAGS_NOT_SUPPORTED
  • PROMOTION_CODE_CONFLICT 409
  • SITE_SUSPENDED 403

MCP tool promotions_create

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/promotions" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"name":"Studio bookings 20% off","kind":"PRODUCT_DISCOUNT","method":"AUTOMATIC","discountType":"PERCENTAGE","percentage":20,"selector":{"kinds":["BOOKING"],"refs":[{"kind":"BOOKING","id":"res_example01"}]},"audienceType":"RETURNING","minPriorPurchases":2}'
Response
{
  "id": "prm_example02",
  "name": "Studio bookings 20% off",
  "kind": "PRODUCT_DISCOUNT",
  "method": "AUTOMATIC",
  "discountType": "PERCENTAGE",
  "code": null,
  "percentage": 20,
  "amounts": [],
  "minQuantity": null,
  "minOrderAmount": null,
  "startsAt": null,
  "endsAt": null,
  "dailyStartMinute": null,
  "dailyEndMinute": null,
  "usageLimit": 100,
  "perCustomerLimit": 1,
  "usageCount": 0,
  "selector": {
    "kinds": [
      "BOOKING"
    ],
    "refs": [
      {
        "kind": "BOOKING",
        "id": "res_example01"
      }
    ]
  },
  "marketIds": [],
  "audienceType": "RETURNING",
  "minPriorPurchases": 2,
  "badgeOverride": null,
  "isActive": true,
  "archivedAt": null,
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Retrieve a promotion

GET/sites/{id}/promotions/{promotionId}
betamarketing:viewdefault (120/minute per token)

Read one promotion, including its selector and per-currency amounts. Errors: FORBIDDEN, PROMOTION_NOT_FOUND.

Parameters

  • idstring · pathrequired

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

  • promotionIdstring · pathrequired

    Promotion id from promotions.list.

Response 200

  • idstringrequired
  • namestringrequired

    Shown to the seller and, for automatic promotions, as the line on the checkout page.

  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    Wizard type; drives the storefront badge and which conditions apply.

  • method"CODE" | "AUTOMATIC"required

    CODE = the buyer enters a code at checkout; AUTOMATIC = applied when conditions match.

  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required

    PERCENTAGE of the matching lines, FIXED_AMOUNT off the order once, or OVERRIDE_PRICE as the per-unit price of matching lines.

  • codestring | nullrequired

    Discount code (uppercase) when method is CODE.

  • percentageinteger | nullrequired

    1–100 when discountType is PERCENTAGE.

  • amountsobject[]required

    Per-currency amount for FIXED_AMOUNT / OVERRIDE_PRICE.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger | nullrequired

    Minimum quantity across matching lines.

  • minOrderAmountinteger | nullrequired

    Minimum discountable subtotal of the order, minor units.

  • startsAtstring | nullrequired

    ISO 8601 start; null = already started.

  • endsAtstring | nullrequired

    ISO 8601 end; null = no end. Required for FLASH_SALE.

  • dailyStartMinuteinteger | nullrequired

    Daily window start, minutes from midnight in the site timezone.

  • dailyEndMinuteinteger | nullrequired

    Daily window end, minutes from midnight in the site timezone.

  • usageLimitinteger | nullrequired

    Total paid orders allowed; null = unlimited.

  • perCustomerLimitinteger | nullrequired

    Paid orders per customer; null = unlimited.

  • usageCountintegerrequired

    Paid orders that redeemed this promotion (refunds are not subtracted).

  • selectorobject | nullrequired
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]required

    Only these markets; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"required

    FIRST_PURCHASE = no paid order yet; RETURNING = at least minPriorPurchases paid orders.

  • minPriorPurchasesinteger | nullrequired

    RETURNING threshold; null = 1.

  • badgeOverridestring | nullrequired

    Custom storefront badge text (automatic promotions only).

  • isActivebooleanrequired
  • archivedAtstring | nullrequired

    Archived promotions are hidden from the dashboard list and never apply.

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PROMOTION_NOT_FOUND 404

MCP tool promotions_get

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/promotions/{promotionId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "id": "prm_example01",
  "name": "Autumn 10% Off",
  "kind": "DISCOUNT_CODE",
  "method": "CODE",
  "discountType": "PERCENTAGE",
  "code": "AUTUMN10",
  "percentage": 10,
  "amounts": [],
  "minQuantity": null,
  "minOrderAmount": null,
  "startsAt": "2026-10-01T02:30:00.000Z",
  "endsAt": null,
  "dailyStartMinute": null,
  "dailyEndMinute": null,
  "usageLimit": 100,
  "perCustomerLimit": 1,
  "usageCount": 14,
  "selector": null,
  "marketIds": [],
  "audienceType": "ALL",
  "minPriorPurchases": null,
  "badgeOverride": null,
  "isActive": true,
  "archivedAt": null,
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Update a promotion

PATCH/sites/{id}/promotions/{promotionId}
betamarketing:managedefault (120/minute per token)

Update a promotion (PATCH: fields left out stay as they are; selector: null means "all lines"; isActive toggles it). Changing a promotion does not affect orders already placed. Errors: FORBIDDEN, VALIDATION (details.code: CODE_REQUIRED, KIND_METHOD_MISMATCH, SCOPE_REQUIRED, START_MUST_BE_BEFORE_END, FLASH_SALE_ENDS_AT_REQUIRED, DAILY_WINDOW_INCOMPLETE, INVALID_PRODUCT, INVALID_VARIANT, INVALID_CATEGORY, INVALID_RESOURCE, INVALID_MARKET, UNSUPPORTED_LINE_KIND, TAGS_NOT_SUPPORTED), PROMOTION_CODE_CONFLICT, SITE_SUSPENDED, PROMOTION_NOT_FOUND.

Parameters

  • idstring · pathrequired

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

  • promotionIdstring · pathrequired

    Promotion id from promotions.list.

Request body

  • namestring
  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"

    DISCOUNT_CODE must use method CODE; the other kinds use AUTOMATIC.

  • method"CODE" | "AUTOMATIC"
  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"
  • codestring

    Required when method is CODE; stored uppercase; unique per site.

  • percentageinteger
  • amountsobject[]

    Required for FIXED_AMOUNT / OVERRIDE_PRICE; one entry per currency.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger
  • minOrderAmountinteger

    Minor units.

  • startsAtstring

    ISO 8601 with offset.

  • endsAtstring

    ISO 8601 with offset; required for FLASH_SALE.

  • dailyStartMinuteinteger
  • dailyEndMinuteinteger

    Must be set together with dailyStartMinute.

  • usageLimitinteger
  • perCustomerLimitinteger
  • selectorobject | null
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]

    Market ids of this site; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"
  • minPriorPurchasesinteger

    Only with audienceType RETURNING.

  • badgeOverridestring
  • isActiveboolean

    Default true on create.

Response 200

  • idstringrequired
  • namestringrequired

    Shown to the seller and, for automatic promotions, as the line on the checkout page.

  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    Wizard type; drives the storefront badge and which conditions apply.

  • method"CODE" | "AUTOMATIC"required

    CODE = the buyer enters a code at checkout; AUTOMATIC = applied when conditions match.

  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required

    PERCENTAGE of the matching lines, FIXED_AMOUNT off the order once, or OVERRIDE_PRICE as the per-unit price of matching lines.

  • codestring | nullrequired

    Discount code (uppercase) when method is CODE.

  • percentageinteger | nullrequired

    1–100 when discountType is PERCENTAGE.

  • amountsobject[]required

    Per-currency amount for FIXED_AMOUNT / OVERRIDE_PRICE.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger | nullrequired

    Minimum quantity across matching lines.

  • minOrderAmountinteger | nullrequired

    Minimum discountable subtotal of the order, minor units.

  • startsAtstring | nullrequired

    ISO 8601 start; null = already started.

  • endsAtstring | nullrequired

    ISO 8601 end; null = no end. Required for FLASH_SALE.

  • dailyStartMinuteinteger | nullrequired

    Daily window start, minutes from midnight in the site timezone.

  • dailyEndMinuteinteger | nullrequired

    Daily window end, minutes from midnight in the site timezone.

  • usageLimitinteger | nullrequired

    Total paid orders allowed; null = unlimited.

  • perCustomerLimitinteger | nullrequired

    Paid orders per customer; null = unlimited.

  • usageCountintegerrequired

    Paid orders that redeemed this promotion (refunds are not subtracted).

  • selectorobject | nullrequired
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]required

    Only these markets; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"required

    FIRST_PURCHASE = no paid order yet; RETURNING = at least minPriorPurchases paid orders.

  • minPriorPurchasesinteger | nullrequired

    RETURNING threshold; null = 1.

  • badgeOverridestring | nullrequired

    Custom storefront badge text (automatic promotions only).

  • isActivebooleanrequired
  • archivedAtstring | nullrequired

    Archived promotions are hidden from the dashboard list and never apply.

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • VALIDATION 400 · details.code: CODE_REQUIRED, KIND_METHOD_MISMATCH, SCOPE_REQUIRED, START_MUST_BE_BEFORE_END, FLASH_SALE_ENDS_AT_REQUIRED, DAILY_WINDOW_INCOMPLETE, INVALID_PRODUCT, INVALID_VARIANT, INVALID_CATEGORY, INVALID_RESOURCE, INVALID_MARKET, UNSUPPORTED_LINE_KIND, TAGS_NOT_SUPPORTED
  • PROMOTION_CODE_CONFLICT 409
  • SITE_SUSPENDED 403
  • PROMOTION_NOT_FOUND 404

MCP tool promotions_update

curl -X PATCH "https://app.kanorio.com/api/v1/sites/{id}/promotions/{promotionId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"selector":{"refs":[{"kind":"PRODUCT","id":"prod_example01","variantId":"tier_example01"}],"priceRange":{"min":50000}},"usageLimit":200}'
Response
{
  "id": "prm_example01",
  "name": "Autumn 10% Off",
  "kind": "DISCOUNT_CODE",
  "method": "CODE",
  "discountType": "PERCENTAGE",
  "code": "AUTUMN10",
  "percentage": 10,
  "amounts": [],
  "minQuantity": null,
  "minOrderAmount": null,
  "startsAt": "2026-10-01T02:30:00.000Z",
  "endsAt": null,
  "dailyStartMinute": null,
  "dailyEndMinute": null,
  "usageLimit": 200,
  "perCustomerLimit": 1,
  "usageCount": 14,
  "selector": {
    "refs": [
      {
        "kind": "PRODUCT",
        "id": "prod_example01",
        "variantId": "tier_example01"
      }
    ],
    "priceRange": {
      "min": 50000
    }
  },
  "marketIds": [],
  "audienceType": "ALL",
  "minPriorPurchases": null,
  "badgeOverride": null,
  "isActive": true,
  "archivedAt": null,
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Delete a promotion

DELETE/sites/{id}/promotions/{promotionId}
betamarketing:managedefault (120/minute per token)

Delete a promotion that was never redeemed. Once a paid order used it the redemption history is an accounting trail, so archive it instead. Errors: FORBIDDEN, PROMOTION_NOT_FOUND, PROMOTION_HAS_REDEMPTIONS.

Parameters

  • idstring · pathrequired

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

  • promotionIdstring · pathrequired

    Promotion id from promotions.list.

Response 200

  • idstringrequired
  • deletedtruerequired

Errors

  • FORBIDDEN 403
  • PROMOTION_NOT_FOUND 404
  • PROMOTION_HAS_REDEMPTIONS 409

MCP tool promotions_delete

curl -X DELETE "https://app.kanorio.com/api/v1/sites/{id}/promotions/{promotionId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "id": "prm_example02",
  "deleted": true
}

Archive a promotion

POST/sites/{id}/promotions/{promotionId}/archive
betamarketing:managedefault (120/minute per token)

Archive a promotion: it stops applying, is hidden from the dashboard list and keeps its redemption history. Idempotent. Errors: FORBIDDEN, PROMOTION_NOT_FOUND.

Parameters

  • idstring · pathrequired

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

  • promotionIdstring · pathrequired

    Promotion id from promotions.list.

Response 200

  • idstringrequired
  • namestringrequired

    Shown to the seller and, for automatic promotions, as the line on the checkout page.

  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    Wizard type; drives the storefront badge and which conditions apply.

  • method"CODE" | "AUTOMATIC"required

    CODE = the buyer enters a code at checkout; AUTOMATIC = applied when conditions match.

  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required

    PERCENTAGE of the matching lines, FIXED_AMOUNT off the order once, or OVERRIDE_PRICE as the per-unit price of matching lines.

  • codestring | nullrequired

    Discount code (uppercase) when method is CODE.

  • percentageinteger | nullrequired

    1–100 when discountType is PERCENTAGE.

  • amountsobject[]required

    Per-currency amount for FIXED_AMOUNT / OVERRIDE_PRICE.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger | nullrequired

    Minimum quantity across matching lines.

  • minOrderAmountinteger | nullrequired

    Minimum discountable subtotal of the order, minor units.

  • startsAtstring | nullrequired

    ISO 8601 start; null = already started.

  • endsAtstring | nullrequired

    ISO 8601 end; null = no end. Required for FLASH_SALE.

  • dailyStartMinuteinteger | nullrequired

    Daily window start, minutes from midnight in the site timezone.

  • dailyEndMinuteinteger | nullrequired

    Daily window end, minutes from midnight in the site timezone.

  • usageLimitinteger | nullrequired

    Total paid orders allowed; null = unlimited.

  • perCustomerLimitinteger | nullrequired

    Paid orders per customer; null = unlimited.

  • usageCountintegerrequired

    Paid orders that redeemed this promotion (refunds are not subtracted).

  • selectorobject | nullrequired
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]required

    Only these markets; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"required

    FIRST_PURCHASE = no paid order yet; RETURNING = at least minPriorPurchases paid orders.

  • minPriorPurchasesinteger | nullrequired

    RETURNING threshold; null = 1.

  • badgeOverridestring | nullrequired

    Custom storefront badge text (automatic promotions only).

  • isActivebooleanrequired
  • archivedAtstring | nullrequired

    Archived promotions are hidden from the dashboard list and never apply.

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PROMOTION_NOT_FOUND 404

MCP tool promotions_archive

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/promotions/{promotionId}/archive" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "prm_example01",
  "name": "Autumn 10% Off",
  "kind": "DISCOUNT_CODE",
  "method": "CODE",
  "discountType": "PERCENTAGE",
  "code": "AUTUMN10",
  "percentage": 10,
  "amounts": [],
  "minQuantity": null,
  "minOrderAmount": null,
  "startsAt": "2026-10-01T02:30:00.000Z",
  "endsAt": null,
  "dailyStartMinute": null,
  "dailyEndMinute": null,
  "usageLimit": 100,
  "perCustomerLimit": 1,
  "usageCount": 14,
  "selector": null,
  "marketIds": [],
  "audienceType": "ALL",
  "minPriorPurchases": null,
  "badgeOverride": null,
  "isActive": false,
  "archivedAt": "2026-10-06T08:00:00.000Z",
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Promotion unarchive

POST/sites/{id}/promotions/{promotionId}/unarchive
betamarketing:managedefault (120/minute per token)

Restore an archived promotion and enable it again. Errors: FORBIDDEN, PROMOTION_NOT_FOUND, SITE_SUSPENDED.

Parameters

  • idstring · pathrequired

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

  • promotionIdstring · pathrequired

    Promotion id from promotions.list.

Response 200

  • idstringrequired
  • namestringrequired

    Shown to the seller and, for automatic promotions, as the line on the checkout page.

  • kind"PRODUCT_DISCOUNT" | "DISCOUNT_CODE" | "QUANTITY_DISCOUNT" | "FLASH_SALE" | "MIN_ORDER"required

    Wizard type; drives the storefront badge and which conditions apply.

  • method"CODE" | "AUTOMATIC"required

    CODE = the buyer enters a code at checkout; AUTOMATIC = applied when conditions match.

  • discountType"PERCENTAGE" | "FIXED_AMOUNT" | "OVERRIDE_PRICE"required

    PERCENTAGE of the matching lines, FIXED_AMOUNT off the order once, or OVERRIDE_PRICE as the per-unit price of matching lines.

  • codestring | nullrequired

    Discount code (uppercase) when method is CODE.

  • percentageinteger | nullrequired

    1–100 when discountType is PERCENTAGE.

  • amountsobject[]required

    Per-currency amount for FIXED_AMOUNT / OVERRIDE_PRICE.

  • amounts[].currencystringrequired

    ISO 4217, case-insensitive; stored lowercase.

  • amounts[].amountintegerrequired

    Minor units (cents; TWD uses 100 = NT$1).

  • minQuantityinteger | nullrequired

    Minimum quantity across matching lines.

  • minOrderAmountinteger | nullrequired

    Minimum discountable subtotal of the order, minor units.

  • startsAtstring | nullrequired

    ISO 8601 start; null = already started.

  • endsAtstring | nullrequired

    ISO 8601 end; null = no end. Required for FLASH_SALE.

  • dailyStartMinuteinteger | nullrequired

    Daily window start, minutes from midnight in the site timezone.

  • dailyEndMinuteinteger | nullrequired

    Daily window end, minutes from midnight in the site timezone.

  • usageLimitinteger | nullrequired

    Total paid orders allowed; null = unlimited.

  • perCustomerLimitinteger | nullrequired

    Paid orders per customer; null = unlimited.

  • usageCountintegerrequired

    Paid orders that redeemed this promotion (refunds are not subtracted).

  • selectorobject | nullrequired
  • selector.kinds"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"[]
  • selector.refsobject[]
  • selector.refs[].kind"PRODUCT" | "BOOKING" | "PREPAID" | "CUSTOM"required
  • selector.refs[].idstringrequired
  • selector.refs[].variantIdstring
  • selector.categoryIdsstring[]
  • selector.tagsstring[]
  • selector.priceRangeobject
  • selector.priceRange.mininteger
  • selector.priceRange.maxinteger
  • marketIdsstring[]required

    Only these markets; empty = every market.

  • audienceType"ALL" | "FIRST_PURCHASE" | "RETURNING"required

    FIRST_PURCHASE = no paid order yet; RETURNING = at least minPriorPurchases paid orders.

  • minPriorPurchasesinteger | nullrequired

    RETURNING threshold; null = 1.

  • badgeOverridestring | nullrequired

    Custom storefront badge text (automatic promotions only).

  • isActivebooleanrequired
  • archivedAtstring | nullrequired

    Archived promotions are hidden from the dashboard list and never apply.

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • PROMOTION_NOT_FOUND 404
  • SITE_SUSPENDED 403

MCP tool promotions_unarchive

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/promotions/{promotionId}/unarchive" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "prm_example01",
  "name": "Autumn 10% Off",
  "kind": "DISCOUNT_CODE",
  "method": "CODE",
  "discountType": "PERCENTAGE",
  "code": "AUTUMN10",
  "percentage": 10,
  "amounts": [],
  "minQuantity": null,
  "minOrderAmount": null,
  "startsAt": "2026-10-01T02:30:00.000Z",
  "endsAt": null,
  "dailyStartMinute": null,
  "dailyEndMinute": null,
  "usageLimit": 100,
  "perCustomerLimit": 1,
  "usageCount": 14,
  "selector": null,
  "marketIds": [],
  "audienceType": "ALL",
  "minPriorPurchases": null,
  "badgeOverride": null,
  "isActive": true,
  "archivedAt": null,
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}