From commercetools
Provides commercetools commerce domain logic: pricing models, discount stacking, shipping predicates, tax modes, payment modeling, Import API patterns, and catalog architecture.
How this skill is triggered — by the user, by Claude, or both
Slash command
/commercetools:commercetools-commerce-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
When this skill is invoked, always follow these steps:
references/approval-rules.mdreferences/as-associate-api.mdreferences/b2b-customer-group-pricing.mdreferences/bopis-shipping.mdreferences/bundle-discounting.mdreferences/bundle-modeling.mdreferences/business-unit-hierarchy.mdreferences/cart-discount-scenarios.mdreferences/custom-associate-roles.mdreferences/customer-group-pricing.mdreferences/discount-code-usage.mdreferences/discount-fundamentals.mdreferences/discount-groups.mdreferences/dynamic-shipping-costs.mdreferences/financing-options.mdreferences/fixed-price-combo.mdreferences/high-precision-money.mdreferences/item-substitutes.mdreferences/limited-time-pricing.mdreferences/payments.mdWhen this skill is invoked, always follow these steps:
Docs search (required, run first) — Always begin by searching docs for this skill. This is the mandatory grounding step: it gathers the latest verified documentation as context for you (the agent). Do not skip it, and do not replace it with another tool (such as an MCP documentation-search tool) This script optimizes for tuned search results — run this command:
node scripts/docs-search.mjs \
--query "<extract key terms from user's question>" \
--app-name "<current-app ex: claude, copilot, codex>" \
--model "<current-model>" \
--skill-name "commercetools-commerce-patterns" \
--limit 10
Use its output as your primary grounding. You may additionally use other tools (such as the commercetools documentation MCP) for deeper, follow-up search.
Combine with skill references — Cross-reference the analysis output with local references in ./references/ for complete context.
Provide implementation guidance — Synthesize the documentation with the specific integration mode the user is targeting.
Fetch GraphQL schema — Run this when you need context about a commercetools GraphQL query or mutation — for example, to inspect a resource's fields, types, and available operations before writing a query, or to verify a GraphQL query/mutation you have just generated against the real schema. It fetches the partial GraphQL SDL for a single commercetools resource:
node scripts/graphql-schemata.mjs \
--resource-name "<commercetools resource, e.g. Cart, Product, Order>" \
--app-name "<current-app, e.g. claude, copilot, cursor, codex>" \
--model "<current-model>" \
--skill-name "commercetools-commerce-patterns"
The output is the GraphQL SDL for that resource. If the resource name is not recognized, the script prints the list of valid resource names — pick the correct one and re-run. Note: the SDL may contain stubbed types — referenced resources rendered as stubs, with their real type name given in a comment. Fetch any you need separately by re-running this script with that type name as --resource-name.
Fetch OpenAPI (REST) schema — Run this when you need context about a commercetools REST endpoint, request/response payload, or update action — for example, to inspect a resource's REST operations before constructing a request, or to verify a REST request/payload you have just generated against the real specification. It fetches the partial OpenAPI specification for a single commercetools resource:
node scripts/openApi-schemata.mjs \
--resource-name "<commercetools resource, e.g. api-Cart-write, api-Customer-read, checkout-Application>" \
--app-name "<current-app, e.g. claude, copilot, cursor, codex>" \
--model "<current-model>" \
--skill-name "commercetools-commerce-patterns"
The output is the OpenAPI specification (YAML) for that resource. REST resources use a read/write-split naming form (e.g. api-Cart-read, api-Cart-write). If the resource name is not recognized, the script prints the list of valid resource names — pick the correct one and re-run. Note: the spec does not include reference-expansion schemas — fetch a referenced resource's schema separately by re-running this script with that resource as --resource-name.
Discount stacking follows a strict priority chain. Product Discounts → Cart Discounts → Discount Codes → Direct Discounts. Direct Discounts on a cart block all Discount Codes. Never mix Direct Discounts and Discount Code flows on the same cart.
sortOrder direction: higher value fires first. For both Product Discounts and Cart Discounts, the discount with the highest sortOrder value (closest to 1) is applied first. 0.9 fires before 0.5. For Product Discounts only one applies (no stacking); for Cart Discounts they stack by default unless stackingMode: StopAfterThisDiscount is set.
Product Discounts cannot be used with external pricing. If a project uses an external price source, Product Discounts are not applied. Use Cart Discounts for any promotional discounts when external pricing is active.
Discount Groups bundle multiple cart discounts under one entity. A Discount Group has its own sortOrder and a "Best deal" prioritization mode — only the cart discount from the group that gives the customer the greatest saving is applied. Use Discount Groups to manage large-scale campaigns (e.g., Black Friday) where deactivating dozens of individual discounts at once would otherwise be error-prone.
Customer Group pricing is set on embedded prices, not at the customer level. A buyer's Customer Groups are resolved at cart calculation time — the price with a matching customerGroup on the variant is selected. A Customer can carry multiple Customer Groups (via customerGroupAssignments, up to 500), and price resolution selects the best qualifying price across all assigned groups. For B2B buyers, assign Customer Groups directly to the buyer's customer record or via the Business Unit.
Cart Score is the key to dynamic shipping rates. Set the project's shipping rate input type to "Cart Score" in Merchant Center. Call setShippingRateInput with a Score type and an integer score. CT will look up the rate tier matching that score. The score must be a non-negative integer.
Cart Score is not available in shipping predicates — copy it to a cart custom field. The score is not directly queryable in predicates. Write the underlying value (e.g., distance in km) to a cart custom field. Write your shipping predicate against that custom field.
Price functions turn cart score into a continuous rate. Configure a priceFunction (e.g., (x / 30)) where x is the cart score. CT evaluates the function and sets the resulting amount as the shipping price, enabling rates that scale smoothly without enumerating every possible value.
Use taxMode: ExternalAmount for most PSP/tax service integrations. This mode lets your tax service calculate the exact tax amount per line item and pass it directly to CT, eliminating rounding discrepancies between CT's engine and external tax services (AvaTax, Vertex).
CT records payment state; the PSP does the actual financial transaction. The Payment object is a ledger. Use addTransaction update actions to track each PSP event (Authorization, Charge, Refund, Chargeback). Only set state: "Success" after confirmed PSP confirmation.
interfaceId on a Payment is immutable once set. This field links CT Payment to the PSP's identifier. Record it correctly the first time — there is no update path.
Cart prices are snapshotted at order creation. If a product price changes between cart creation and order creation, the cart holds the old price. Use the recalculate action on the cart to refresh prices before checkout.
Business Units are the core B2B entity — all B2B operations run through them. All B2B operations use the as-associate API chain (construction and scope in references/as-associate-api.md). Never use project-level cart/order APIs for B2B user-facing operations.
The quote lifecycle has four entities: QuoteRequest → StagedQuote → Quote → Order. A buyer creates a QuoteRequest; a sales rep creates a StagedQuote (working draft with negotiated prices); the Quote is the finalized offer; if accepted, the buyer converts it to an Order. Each step has its own state machine.
POST /orders vs POST /recurring-orders produce fundamentally different results. Calling POST /orders on a cart with recurring line items creates both a regular order (immediate) and a recurring order. Calling POST /recurring-orders creates only the recurring order. Use /orders for "subscribe and ship now" flow; use /recurring-orders for future-dated subscriptions.
Cart discount recurringOrderScope controls whether a discount repeats. Set "NonRecurringOrdersOnly" for one-time welcome promotions. Set "AnyOrder" for standing loyalty discounts that should apply on every recurrence cycle.
| Topic | Reference |
|---|---|
| Discount stacking rules, sortOrder, Direct Discount blocking Discount Codes | references/discount-fundamentals.md |
| Buy/Get cart discount — triggerPattern, targetPattern, excludeCount | references/bundle-discounting.md |
| Cart discount scenario cookbook — 12 named scenarios with full JSON | references/cart-discount-scenarios.md |
| Fixed-price combo discount — buy N of X+Y at fixed combined price | references/fixed-price-combo.md |
"Any N of a set for one fixed total price" (no trigger item), and per-cart firing caps via maxOccurrence | references/cart-discount-scenarios.md |
| Customer Group-based pricing — embedded price selection, group assignment | references/customer-group-pricing.md |
| B2B customer group pricing — buyer-specific pricing via Customer Groups | references/b2b-customer-group-pricing.md |
| High Precision Money — fractionDigits, currency configuration, rounding | references/high-precision-money.md |
| Discount Groups and Promotion Prioritization — best-deal selection | references/discount-groups.md |
| Store credit & loyalty currency — external ledger pattern | references/store-credit.md |
| Limited-time pricing — validFrom/validUntil on embedded prices | references/limited-time-pricing.md |
| Discount code usage — code generation, redemption limits | references/discount-code-usage.md |
| Topic | Reference |
|---|---|
| Tiered rates, cart score setup, ScoreShippingRateInput | references/tiered-rates-cart-score.md |
| Shipping predicates — predicate syntax, custom field workaround | references/shipping-predicates.md |
| Price functions — priceFunction configuration, function syntax | references/price-functions.md |
| Dynamic shipping costs — external calculation, setCustomShippingMethod | references/dynamic-shipping-costs.md |
| BOPIS shipping — multiple shipping methods, delivery group setup | references/bopis-shipping.md |
| Topic | Reference |
|---|---|
| Payments — Payment object model, transactions, PSP integration flow | references/payments.md |
| Taxes — cart tax modes (Platform/External/ExternalAmount/Disabled) | references/taxes.md |
| Financing & installments — BNPL integration, CT payment modeling | references/financing-options.md |
| Topic | Reference |
|---|---|
| Custom Associate Roles — role definition, permission keys, assignment to BU | references/custom-associate-roles.md |
| Business Unit hierarchy — parent/child BUs, inherited roles, store assignment | references/business-unit-hierarchy.md |
| Approval rules — predicate design, approval flow lifecycle | references/approval-rules.md |
| Quote lifecycle — QuoteRequest, StagedQuote, Quote, Order conversion | references/quote-lifecycle.md |
| as-associate API pattern — chain construction, scope | references/as-associate-api.md |
| Topic | Reference |
|---|---|
| Recurring orders — RecurrencePolicy, priceSelectionMode, /orders vs /recurring-orders | references/recurring-orders.md |
| Topic | Reference |
|---|---|
| Product data modeling — hierarchy, all 14 attribute types, Nested vs Custom Object | references/product-data-modeling.md |
| Bundle product modeling — ProductType design, child SKU reference, BFF orchestration | references/bundle-modeling.md |
| Import API — containers, batching, async processing, delta imports | references/import-api.md |
| Import API performance — 15M record pattern, container count, batch size | references/import-performance.md |
| Item substitutes — modeling substitute/replacement products | references/item-substitutes.md |
| Inventory modeling — supply channels, inventory entries, backorder | references/inventory-modeling.md |
0.9 is applied before 0.5. This is a common misconception that causes incorrect promotion behavior.CountOnLineItemUnits entry can only match one SKU — add separate entries per bundle component.setShippingRateInput must be called before checkout and before shipping rate totals are calculated. Calling it after order creation has no effect.GET /shipping-methods?cartId=<id>.as-associate API chain. Project-level apiRoot.carts().* does not enforce B2B permissions. This is a security requirement, not just a convention.CreateMyCarts permission to add items to a cart as-associate. Missing permissions result in a 403.POST /orders creates both a regular order and recurring orders from a mixed cart. Design the order confirmation flow to handle multiple order IDs.Success before PSP confirmation. Optimistic success marking creates reconciliation failures.interfaceId on a Payment cannot be changed once set. Record the PSP transaction identifier correctly on the first write.productDraftImport is destructive. Any field not included in the draft is deleted.maxApplications is global across all customers. Use maxApplicationsPerCustomer for per-customer limits — they are separate fields.priceSelectionMode must be set intentionally per use case. "Fixed" provides price guarantee; "Dynamic" always applies current catalog pricing.recurringOrderScope on cart discounts defaults to applying on all orders. Explicitly set "NonRecurringOrdersOnly" for introductory discounts.isActive on a Cart Discount is a soft toggle. Use this for scheduled campaigns rather than creating/deleting discounts.stackingMode: StopAfterThisDiscount to make a specific discount exclusive. Cart discounts stack by default.priceRoundingMode (on Cart/Order/Quote and as a Project default). Modes: HalfEven (banker's rounding — the default), HalfUp, HalfDown. Only HalfDown rounds .5 in the customer's favor; align the mode with your ERP/tax system and budget margin accordingly for high-volume campaigns.lineItemGrossTotal(categories.key = (...)) >= "X.XX USD" is the pattern for category spend thresholds. The currency string must be included in the value.validFrom/validUntil for time-limited pricing without product republication.npx claudepluginhub commercetools/commercetools-ai-plugins --plugin commercetoolsCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.