--- title: Cart Instructions API description: >- Check which cart mutations are allowed before calling them. Verify permissions for discounts, attributes, delivery, lines, metafields, and notes. api_version: 2026-04 api_name: checkout-ui-extensions source_url: html: >- https://shopify.dev/docs/api/checkout-ui-extensions/latest/target-apis/checkout-apis/cart-instructions-api md: >- https://shopify.dev/docs/api/checkout-ui-extensions/latest/target-apis/checkout-apis/cart-instructions-api.md --- # Cart Instructions API The Cart Instructions API provides flags that indicate which cart mutations are allowed in the current checkout context. Use this API to determine which mutations are available before rendering features that modify the cart. Cart instruction flags are read-only. Your extension can't change whether a mutation is permitted. It can only check the current value and respond accordingly. ### Use cases * **Gate discount features**: Only render discount code UI when the checkout allows discount changes. * **Gate attribute controls**: Only show preference controls like gift wrapping when the checkout allows attribute changes. * **Gate cart modifications**: Only offer features like free gifts or quantity changes when the checkout allows line item updates. ### Support Targets (31) ### Supported targets * [purchase.​checkout.​actions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/navigation#navigation-target) * [purchase.​checkout.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/block#block-target) * [purchase.​checkout.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/order-summary#line-item-targets) * [purchase.​checkout.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/order-summary#checkout-cart-line-list-) * purchase.​checkout.​chat.​render * [purchase.​checkout.​contact.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/information#information-target) * [purchase.​checkout.​delivery-address.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/shipping#render-after-delivery-address-) * [purchase.​checkout.​delivery-address.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/shipping#delivery-address-targets) * [purchase.​checkout.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/footer#footer-target) * [purchase.​checkout.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/header#header-target) * [purchase.​checkout.​payment-method-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/payment#render-after-payment-methods-) * [purchase.​checkout.​payment-method-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/payment#payment-targets) * [purchase.​checkout.​pickup-location-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/local-pickup#render-after-pickup-locations-) * [purchase.​checkout.​pickup-location-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/local-pickup#location-list-targets) * [purchase.​checkout.​pickup-location-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/local-pickup#location-option-item-target) * [purchase.​checkout.​pickup-point-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/pickup-points#render-after-pickup-points-) * [purchase.​checkout.​pickup-point-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/pickup-points#pickup-points-targets) * [purchase.​checkout.​reductions.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/order-summary#checkout-reductions-after-) * [purchase.​checkout.​reductions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/order-summary#reductions-targets) * [purchase.​checkout.​shipping-option-item.​details.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/shipping#shipping-option-item-targets) * [purchase.​checkout.​shipping-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/shipping#render-after-shipping-option-) * [purchase.​checkout.​shipping-option-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/shipping#render-after-shipping-options-) * [purchase.​checkout.​shipping-option-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/checkout/shipping#shipping-option-list-targets) * [purchase.​thank-you.​announcement.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/announcement#thank-you-announcement-) * [purchase.​thank-you.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/block#block-target) * [purchase.​thank-you.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/order-summary#line-item-targets) * [purchase.​thank-you.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/order-summary#thank-you-cart-line-list-) * purchase.​thank-you.​chat.​render * [purchase.​thank-you.​customer-information.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/information#information-target) * [purchase.​thank-you.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/footer#footer-target) * [purchase.​thank-you.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-04/targets/thank-you/header#header-target) ### Properties The [`shopify` global object](https://shopify.dev/docs/api/checkout-ui-extensions/latest#target-apis-define-what-your-extension-does) provides cart instruction data for the current checkout. Access the following properties on `shopify` to check which cart mutations are allowed. Available to `purchase` extension targets. * **instructions** **SubscribableSignalLike\** **required** The cart instructions used to create the checkout and possibly limit extension capabilities. These instructions should be checked before performing any actions that might be affected by them. For example, if you intend to add a discount code via the `applyDiscountCodeChange` method, check `discounts.canUpdateDiscountCodes` to ensure it's supported in this checkout. **Caution:** Check cart instructions before calling select APIs, as \> some may not be available. See the \> \Cart Instructions API\ \> for more information. ### SubscribableSignalLike Represents a reactive signal interface that provides both immediate value access and subscription-based updates. Enables real-time synchronization with changing data through the observer pattern. This interface extends \`ReadonlySignalLike\` with deprecated fields that are still supported for backwards compatibility. * current The current value of the signal. Equivalent to \`.value\`, accessing this property subscribes to changes when used in a reactive context. ```ts T ``` * destroy Cleans up the subscription and releases any resources held by this signal. After calling \`destroy()\`, the signal stops receiving updates from the main thread. ```ts () => Promise ``` * subscribe Subscribes to value changes and calls the provided function whenever the value updates. Returns an unsubscribe function to clean up the subscription. Use to automatically react to changes in the signal's value. ```ts (fn: (value: T) => void) => () => void ``` * value The current value of the signal. This property provides immediate access to the current value without requiring subscription setup. Use for one-time value checks or initial setup. ```ts T ``` ### CartInstructions * attributes Whether the extension can update custom attributes using \`applyAttributeChange()\`. ```ts AttributesCartInstructions ``` * delivery Whether the extension can modify the shipping address using \`applyShippingAddressChange()\`. ```ts DeliveryCartInstructions ``` * discounts Whether the extension can add or remove discount codes using \`applyDiscountCodeChange()\`. ```ts DiscountsCartInstructions ``` * lines Whether the extension can add, remove, or update cart lines using \`applyCartLinesChange()\`. ```ts CartLinesCartInstructions ``` * metafields Whether the extension can add, update, or delete cart metafields using \`applyMetafieldChange()\`. ```ts MetafieldsCartInstructions ``` * notes Whether the extension can update the order note using \`applyNoteChange()\`. ```ts NotesCartInstructions ``` ### AttributesCartInstructions * canUpdateAttributes Whether attributes can be updated using \`applyAttributeChange()\`. When \`false\`, the checkout configuration doesn't allow attribute changes. Even when \`true\`, calls to \`applyAttributeChange()\` can still fail during accelerated checkout (Apple Pay, Google Pay). ```ts boolean ``` ### DeliveryCartInstructions * canSelectCustomAddress Whether the shipping address can be modified using \`applyShippingAddressChange()\`. When \`false\`, the buyer is using an accelerated checkout flow (Apple Pay, Google Pay) where the address can't be changed. ```ts boolean ``` ### DiscountsCartInstructions * canUpdateDiscountCodes Whether discount codes can be updated using \`applyDiscountCodeChange()\`. When \`false\`, the checkout configuration doesn't allow discount code changes. Even when \`true\`, calls to \`applyDiscountCodeChange()\` can still fail during accelerated checkout (Apple Pay, Google Pay). ```ts boolean ``` ### CartLinesCartInstructions * canAddCartLine Whether new cart lines can be added using \`applyCartLinesChange()\`. When \`false\`, the checkout configuration doesn't allow adding lines (for example, draft orders). Even when \`true\`, calls can still fail during accelerated checkout (Apple Pay, Google Pay). ```ts boolean ``` * canRemoveCartLine Whether cart lines can be removed using \`applyCartLinesChange()\`. When \`false\`, the checkout configuration doesn't allow removing lines. Even when \`true\`, calls can still fail during accelerated checkout. ```ts boolean ``` * canUpdateCartLine Whether cart lines can be updated using \`applyCartLinesChange()\`. When \`false\`, the checkout configuration doesn't allow updating lines. Even when \`true\`, calls can still fail during accelerated checkout. ```ts boolean ``` ### MetafieldsCartInstructions * canDeleteCartMetafield Whether the extension can delete cart metafields using \`applyMetafieldChange()\`. ```ts boolean ``` * canSetCartMetafields Whether the extension can add or update cart metafields using \`applyMetafieldChange()\`. ```ts boolean ``` ### NotesCartInstructions * canUpdateNote Whether the order note can be updated using \`applyNoteChange()\`. When \`false\`, the checkout configuration doesn't allow note changes. Even when \`true\`, calls to \`applyNoteChange()\` can still fail during accelerated checkout (Apple Pay, Google Pay). ```ts boolean ``` Examples ### Examples * #### ##### Description Render a discount button only when discount codes can be updated. This example checks \`instructions.discounts.canUpdateDiscountCodes\` and calls \`shopify.applyDiscountCodeChange\` when allowed, showing a warning banner when blocked. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { if ( shopify.instructions.value.discounts .canUpdateDiscountCodes ) { return ( shopify.applyDiscountCodeChange({ type: 'addDiscountCode', code: 'FREE_SHIPPING', }) } > Apply your loyalty discount ); } else { return ( Loyalty discounts are unavailable ); } } ``` * #### ##### Description Apply a loyalty bonus attribute when cart attributes are writable. This example checks \`instructions.attributes.canUpdateAttributes\` and calls \`shopify.applyAttributeChange\` when allowed. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { if ( shopify.instructions.value.attributes .canUpdateAttributes ) { return ( shopify.applyAttributeChange({ type: 'updateAttribute', key: 'loyaltyPoints', value: '100', }) } > Apply 100 loyalty points ); } else { return ( Loyalty points are unavailable ); } } ``` * #### ##### Description Offer a postal code change when the shipping address is editable. This example checks \`instructions.delivery.canSelectCustomAddress\` and calls \`shopify.applyShippingAddressChange\` when allowed. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { if ( shopify.instructions.value.delivery .canSelectCustomAddress ) { return ( shopify.applyShippingAddressChange?.({ type: 'updateShippingAddress', address: { zip: '90201', }, }) } > Change your postal code ); } else { return ( Shipping address cannot be modified ); } } ``` * #### ##### Description Present a free gift option when cart lines can be added. This example checks \`instructions.lines.canAddCartLine\` and calls \`shopify.applyCartLinesChange\` when allowed. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { if ( shopify.instructions.value.lines .canAddCartLine ) { return ( shopify.applyCartLinesChange({ type: 'addCartLine', merchandiseId: 'gid://shopify/product/1234', quantity: 1, }) } > Add a free gift to your order ); } else { return ( The products in your cart cannot be modified ); } } ``` * #### ##### Description Save a loyalty value to a cart metafield when writes are permitted. This example checks \`instructions.metafields.canSetCartMetafields\` and calls \`shopify.applyMetafieldChange\` when allowed. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { if ( shopify.instructions.value.metafields .canSetCartMetafields ) { return ( shopify.applyMetafieldChange({ type: 'updateCartMetafield', metafield: { namespace: 'loyalty', key: 'loyaltyPoints', value: '100', type: 'string', }, }) } > Apply 100 loyalty points ); } else { return ( Loyalty points are unavailable ); } } ``` * #### ##### Description Add a gift message to the order note when updates are allowed. This example checks \`instructions.notes.canUpdateNote\` and calls \`shopify.applyNoteChange\` when allowed. ##### jsx ```jsx import '@shopify/ui-extensions/preact'; import {render} from 'preact'; export default function extension() { render(, document.body); } function Extension() { if ( shopify.instructions.value.notes.canUpdateNote ) { return ( shopify.applyNoteChange({ type: 'updateNote', note: 'Please include a free gift.', }) } > Include a free gift with your order ); } else { return ( Free gifts cannot be added to this order ); } } ``` *** ## Best practices * **Always check instructions before mutations**: Don't call mutation methods like `applyDiscountCodeChange` without first verifying the corresponding instruction flag. Unchecked calls fail silently or return errors. * **Hide features when blocked**: When an instruction returns `false`, hide the entire feature rather than showing a disabled button. This prevents confusion about why a feature is unavailable. *** ## Limitations * Instruction values can change between checkout steps. A mutation that's allowed on the shipping step might be blocked on the payment step. ***