---
title: Cart Instructions API
description: >-
  Check which cart mutations are allowed before calling them, including
  discounts, attributes, delivery, lines, metafields, and notes.
api_version: 2026-07-rc
source_url:
  html: >-
    https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/target-apis/checkout-apis/cart-instructions-api
  md: >-
    https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/target-apis/checkout-apis/cart-instructions-api.md
api_name: checkout-ui-extensions
---

# 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-07-rc/targets/checkout/navigation#navigation-target)
* [purchase.​checkout.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/block#block-target)
* [purchase.​checkout.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/order-summary#line-item-targets)
* [purchase.​checkout.​cart-line-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/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-07-rc/targets/checkout/information#information-target)
* [purchase.​checkout.​delivery-address.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/shipping#render-after-delivery-address-)
* [purchase.​checkout.​delivery-address.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/shipping#delivery-address-targets)
* [purchase.​checkout.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/footer#footer-target)
* [purchase.​checkout.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/header#header-target)
* [purchase.​checkout.​payment-method-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/payment#render-after-payment-methods-)
* [purchase.​checkout.​payment-method-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/payment#payment-targets)
* [purchase.​checkout.​pickup-location-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/local-pickup#render-after-pickup-locations-)
* [purchase.​checkout.​pickup-location-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/local-pickup#location-list-targets)
* [purchase.​checkout.​pickup-location-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/local-pickup#location-option-item-target)
* [purchase.​checkout.​pickup-point-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/pickup-points#render-after-pickup-points-)
* [purchase.​checkout.​pickup-point-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/pickup-points#pickup-points-targets)
* [purchase.​checkout.​reductions.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/order-summary#checkout-reductions-after-)
* [purchase.​checkout.​reductions.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/order-summary#reductions-targets)
* [purchase.​checkout.​shipping-option-item.​details.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/shipping#shipping-option-item-targets)
* [purchase.​checkout.​shipping-option-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/shipping#render-after-shipping-option-)
* [purchase.​checkout.​shipping-option-list.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/shipping#render-after-shipping-options-)
* [purchase.​checkout.​shipping-option-list.​render-before](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/checkout/shipping#shipping-option-list-targets)
* [purchase.​thank-you.​announcement.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/thank-you/announcement#thank-you-announcement-)
* [purchase.​thank-you.​block.​render](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/thank-you/block#block-target)
* [purchase.​thank-you.​cart-line-item.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/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-07-rc/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-07-rc/targets/thank-you/information#information-target)
* [purchase.​thank-you.​footer.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/thank-you/footer#footer-target)
* [purchase.​thank-you.​header.​render-after](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc/targets/thank-you/header#header-target)

### Properties

The [`shopify` global object](https://shopify.dev/docs/api/checkout-ui-extensions/2026-07-rc#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\<CartInstructions>**

  **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 \&gt; some may not be available. See the \&gt; \<a href="/docs/api/checkout-ui-extensions/2026-07-rc/apis/cart-instructions#examples">Cart Instructions API\</a> \&gt; 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<void>
  ```

* 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(<Extension />, document.body);
  }

  function Extension() {
    if (
      shopify.instructions.value.discounts
        .canUpdateDiscountCodes
    ) {
      return (
        <s-button
          onClick={() =>
            shopify.applyDiscountCodeChange({
              type: 'addDiscountCode',
              code: 'FREE_SHIPPING',
            })
          }
        >
          Apply your loyalty discount
        </s-button>
      );
    } else {
      return (
        <s-banner tone="warning">
          Loyalty discounts are unavailable
        </s-banner>
      );
    }
  }
  ```

* ####

  ##### 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(<Extension />, document.body);
  }

  function Extension() {
    if (
      shopify.instructions.value.attributes
        .canUpdateAttributes
    ) {
      return (
        <s-button
          onClick={() =>
            shopify.applyAttributeChange({
              type: 'updateAttribute',
              key: 'loyaltyPoints',
              value: '100',
            })
          }
        >
          Apply 100 loyalty points
        </s-button>
      );
    } else {
      return (
        <s-banner tone="warning">
          Loyalty points are unavailable
        </s-banner>
      );
    }
  }
  ```

* ####

  ##### 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(<Extension />, document.body);
  }

  function Extension() {
    if (
      shopify.instructions.value.delivery
        .canSelectCustomAddress
    ) {
      return (
        <s-button
          onClick={() =>
            shopify.applyShippingAddressChange?.({
              type: 'updateShippingAddress',
              address: {
                zip: '90201',
              },
            })
          }
        >
          Change your postal code
        </s-button>
      );
    } else {
      return (
        <s-banner tone="warning">
          Shipping address cannot be modified
        </s-banner>
      );
    }
  }
  ```

* ####

  ##### 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(<Extension />, document.body);
  }

  function Extension() {
    if (
      shopify.instructions.value.lines
        .canAddCartLine
    ) {
      return (
        <s-button
          onClick={() =>
            shopify.applyCartLinesChange({
              type: 'addCartLine',
              merchandiseId:
                'gid://shopify/product/1234',
              quantity: 1,
            })
          }
        >
          Add a free gift to your order
        </s-button>
      );
    } else {
      return (
        <s-banner tone="warning">
          The products in your cart cannot be
          modified
        </s-banner>
      );
    }
  }
  ```

* ####

  ##### 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(<Extension />, document.body);
  }

  function Extension() {
    if (
      shopify.instructions.value.metafields
        .canSetCartMetafields
    ) {
      return (
        <s-button
          onClick={() =>
            shopify.applyMetafieldChange({
              type: 'updateCartMetafield',
              metafield: {
                namespace: 'loyalty',
                key: 'loyaltyPoints',
                value: '100',
                type: 'string',
              },
            })
          }
        >
          Apply 100 loyalty points
        </s-button>
      );
    } else {
      return (
        <s-banner tone="warning">
          Loyalty points are unavailable
        </s-banner>
      );
    }
  }
  ```

* ####

  ##### 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(<Extension />, document.body);
  }

  function Extension() {
    if (
      shopify.instructions.value.notes.canUpdateNote
    ) {
      return (
        <s-button
          onClick={() =>
            shopify.applyNoteChange({
              type: 'updateNote',
              note: 'Please include a free gift.',
            })
          }
        >
          Include a free gift with your order
        </s-button>
      );
    } else {
      return (
        <s-banner tone="warning">
          Free gifts cannot be added to this order
        </s-banner>
      );
    }
  }
  ```

***

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

***
