data-src=../../../../includes/saas-only.md

setNominatedSourceOnCartItems mutation

The setNominatedSourceOnCartItems mutation is the single canonical write path for a nomination. Specify a source_code to set a nomination, or null or an empty string to clear it.

Domain validation failures are returned for each item in rejected_items, which allows valid nominations in the same request to succeed. An invalid or foreign cart_item_uid, or any other malformed input, fails the entire operation with a GraphQL input error before any nomination is written.

Reference

The setNominatedSourceOnCartItems reference provides detailed information about the types and fields defined in this mutation.

Configure the storefront query

By default, this inventory information is not accessible on the storefront. To enable it, complete the following steps.

Enable the per-source availability query

The per-source portion of the sourceAvailability query is disabled by default because it discloses which sources stock a SKU. Enable it for each store view.

  1. In the Admin, go to Stores > Settings > Configuration > Catalog > Inventory > Per-Source Availability (Storefront).

  2. Set Enable sourceAvailability GraphQL Query to Yes and save the configuration.

While this setting is disabled, the sourceAvailability query returns an empty list. The stockAvailability query does not disclose sources and is not affected by this setting.

For more information, see Global options and Inventory configuration.

Make a source visible on the storefront

Even when the query is enabled, a source is reported only if it is explicitly flagged.

  1. In the Admin, go to Stores > Inventory > Sources and edit a source.

  2. Enable Visible on Storefront and save the source.

A source is reported on the storefront only when it is assigned to the stock of the current sales channel.

For more information, see Add a source in the Adobe Commerce Admin Systems Guide.

Get the cart item UID

The mutation requires the masked cart ID and the UID of each cart item to nominate. Create a cart with the createGuestCart mutation or retrieve one with the customerCart query, add products to it, and then query the cart items.

Request:

query GetCartItems($cartId: String!) {
  cart(cart_id: $cartId) {
    itemsV2 {
      items {
        uid
        product { sku name }
        quantity
      }
    }
  }
}

Response:

{
  "data": {
    "cart": {
      "itemsV2": {
        "items": [
          { "uid": "OTk=", "product": { "sku": "24-MB01", "name": "Joust Duffle Bag" }, "quantity": 1
          }
        ]
      }
    }
  }
}

Set the nominated source

The following mutation nominates the store_nyc_001 source for one cart item.

Request:

mutation SetSource($cartId: String!) {
  setNominatedSourceOnCartItems(
    input: {
      cart_id: $cartId
      items: [{ cart_item_uid: "OTk=", source_code: "store_nyc_001" }]
    }
  ) {
    cart {
      itemsV2 {
        items {
          uid
          nominated_source { source_code name is_in_stock available_qty }
          nominated_source_errors { code message }
        }
      }
    }
    rejected_items {
      cart_item_uid
      code
      message
      requested_qty
      available_qty
    }
  }
}

Response:

{
  "data": {
    "setNominatedSourceOnCartItems": {
      "cart": {
        "itemsV2": {
          "items": [
            {
              "uid": "OTk=",
              "nominated_source": {
                "source_code": "store_nyc_001",
                "name": "NYC Flagship Store",
                "is_in_stock": true,
                "available_qty": null
              },
              "nominated_source_errors": []
            }
          ]
        }
      },
      "rejected_items": []
    }
  }
}
data-variant=info
data-slots=text
Setting a pickup_location_code with the setShippingAddressesOnCart mutation automatically nominates that location as the source for every cart item. In-store pickup reuses this write path internally, so no separate call is required.

Handle rejected items

When a nomination fails domain validation, the item is returned in rejected_items and the remaining nominations in the request are applied. The following response shows one item that does not have the necessary quantity available at the selected source.

{
  "data": {
    "setNominatedSourceOnCartItems": {
      "cart": { "itemsV2": { "items": [ <...> ] } },
      "rejected_items": [
        {
          "cart_item_uid": "MTAw",
          "code": "NOT_ENOUGH_QTY",
          "message": "Not enough quantity at the selected source.",
          "requested_qty": 5,
          "available_qty": 2
        }
      ]
    }
  }
}

The code field returns one of the following NominatedSourceErrorCode values.

Code
Description
UNKNOWN_SOURCE
The source_code value does not exist.
SOURCE_DISABLED
The source exists, but it is disabled.
NOT_ENOUGH_QTY
The available quantity at the source is less than the quantity of the item.
SKU_SOURCE_CONFLICT
The same SKU is already nominated to a different source on another cart line. A cart supports one nominated source per SKU.

Review nominated sources in the Admin

After orders begin to carry nominations, you can review each nomination and receive early validation in the Admin:

data-variant=info
data-slots=text
Authoritative shipment enforcement occurs outside the Admin and rejects a deduction from the wrong source for non-Admin callers, such as REST clients and asynchronous consumers.

Read availability and saleability

Two queries report availability, and you can request both in a single GraphQL request:

Each query accepts a maximum of 100 skus values. The sourceAvailability query also accepts a maximum of 100 source_codes values. Consider splitting larger lists into batches that stay within these limits.

Request:

query Availability {
  stockAvailability(skus: ["24-MB01"]) {
    sku
    salable_qty
    is_in_stock
    is_salable           # authoritative Add to Cart gate (backorders considered)
    backorder_message    # pre-order notice, or null
  }
  sourceAvailability(skus: ["24-MB01"], only_in_stock: true) {
    sku
    sources {
      source_code
      name
      is_in_stock
      available_qty
      is_pickup_location_active
    }
  }
}

Response:

{
  "data": {
    "stockAvailability": [
      {
        "sku": "24-MB01",
        "salable_qty": null,
        "is_in_stock": true,
        "is_salable": true,
        "backorder_message": null
      }
    ],
    "sourceAvailability": [
      {
        "sku": "24-MB01",
        "sources": [
          {
            "source_code": "store_nyc_001",
            "name": "NYC Flagship Store",
            "is_in_stock": true,
            "available_qty": null,
            "is_pickup_location_active": true
          }
        ]
      }
    ]
  }
}

For the full argument and type reference, see the stockAvailability and sourceAvailability queries.

Gate Add to Cart on is_salable

Use the stockAvailability is_salable field, not is_in_stock, to determine whether a shopper can add a product to the cart. The is_salable field is the authoritative purchase-eligibility signal and accounts for backorders, the minimum sale quantity, and quantity increments. It is true when the SKU is in stock, or when the SKU is out of stock but backorders are enabled, which indicates a pre-order.

The per-source is_in_stock field is a physical-inventory statement about a single source. It can be false for a SKU that remains purchasable through backorder, so gating the Add to Cart button on it incorrectly hides pre-order products. The stockAvailability query returns is_salable for every visible SKU, regardless of the per-source disclosure setting for the store.

Identify pre-order products

The stockAvailability backorder_message field only populates when the SKU is salable solely because notify-mode backorders are enabled, meaning the SKU is salable but not in stock. The field is null when the SKU is in stock, when backorders are silent, or when the SKU is not salable. Use the presence of a message to render a pre-order label next to the Add to Cart button.

Interpret quantities

The available_qty and salable_qty fields return an exact quantity only when the quantity is at or below the Only X left Threshold setting. Above the threshold, the fields return null. The threshold defaults to 0, so by default every positive quantity is masked and the boolean fields carry the information.

Control source visibility

The sourceAvailability query returns results only when per-source disclosure is enabled, and the sources list is narrowed to the storefront-visible sources in the stock of the current sales channel. When disclosure is disabled, the query returns an empty list. Use stockAvailability for per-SKU availability on those stores.

Specify source_codes to restrict the report to named sources. A requested source that is not visible on the storefront, or that is not assigned to the stock of the sales channel, is silently omitted. Omit only_in_stock, which defaults to false, to include out-of-stock sources.

Read nomination fields on cart items

Any cart query can read the live state of the nomination on an item through the following fields:

Order lifecycle

After an order that contains nominations is placed, the reservation lifecycle runs automatically.

  1. Quote to order. The nomination is copied from the quote item to the order item and persisted as the source of truth for the line.

  2. Placement. A hold is recorded at the nominated source for each nominated line, and the stock-level reservation is suppressed for that line so the hold is not counted twice. A placement validation rule rejects the order if the nominated source cannot cover the line. The open hold is also included in the shared salable quantity total, so both the displayed quantity and the Add to Cart guard account for it while the order is unshipped.

  3. Shipment. A release is recorded at the nominated source, and the physical deduction is forced to that same source. A mismatched source is rejected before any decrement occurs. The hold and the release net to zero.

  4. Cancellation. For each nominated line that has an open hold, a release is recorded at the nominated source. Only the unshipped quantity is compensated, because quantity that was already shipped was released during shipment. Cancellation is an alternative to shipment, not a later step.

  5. Cleanup. A daily cron job removes fully compensated rows from the append-only reservation ledger.