Quick Order in Magento 2: The Backend API Behind SKU-Based Fast Ordering
AI generated
M2
di.xml
Magento 2 · B2B Suite
Quick Order
The backend API behind SKU-based fast ordering

Quick Order lets company customers order directly from a list of SKUs and quantities without clicking through the catalog, backed by the same GraphQL mutation available for custom frontend implementations such as a CSV upload. Building a custom interface on top of it means knowing the validation logic, the structured error codes, and the performance limits with large SKU lists.

11 min read Quick Order · B2B Suite Magento 2.4.x Commerce

1. Placing Quick Order in the B2B storefront

Quick Order is a storefront feature of the B2B Suite that lets company customers enter or paste a list of SKUs and quantities directly, instead of finding every product individually through search or category navigation. Functionally, the feature targets customers who know exactly what they want to order, for example from their own internal order list or a price list export.

Technically, Quick Order is not a standalone new API but a dedicated storefront interface over the same cart mutation Magento also uses for regularly adding multiple products to the cart. The actual value of Quick Order therefore sits less in the backend and more in the combination of a fast input mask, autocomplete, and a response structure specifically designed for many simultaneous line items.

2. The flow: from SKU list to cart

The flow behind Quick Order breaks down into three steps: first, the entered list of SKU-quantity pairs is submitted to the backend; then each individual line is validated against the product catalog, price, and stock; finally, all valid lines are added together to the active cart. Invalid lines do not automatically block the valid ones, but are reported back separately.

This behavior deliberately differs from a classic form submit with all-or-nothing logic. For a list of fifty lines where two are invalid, the remaining forty-eight are still added to the cart, while the two faulty lines are reported back with a concrete error code, so the customer can fix exactly those instead of repeating the entire input.

3. The underlying GraphQL mutation

On the backend, a Quick Order request runs through the same addProductsToCart mutation used for other bulk cart operations. It accepts a list of cart items with SKU and quantity, and the response returns both the updated cart and a list of user_errors, where every failed line is listed individually with a descriptive error code.

For custom frontend implementations it matters to consistently evaluate this response structure instead of just checking whether the mutation overall succeeded. A mutation without a technical error can still contain several user_errors when individual lines could not be added for functional reasons, for example because a SKU does not exist or a product is currently not salable.


mutation QuickOrderAddToCart {
  addProductsToCart(
    cartId: "abc123cartid"
    cartItems: [
      { sku: "SKU-1001", quantity: 5 }
      { sku: "SKU-1002", quantity: 12 }
      { sku: "SKU-UNKNOWN", quantity: 3 }
    ]
  ) {
    cart {
      id
      total_quantity
    }
    user_errors {
      code
      message
    }
  }
}

4. Building custom CSV upload frontends

For a CSV upload that goes beyond the default Quick Order input mask, the same mutation can be reused: the CSV file is parsed, converted into a list of SKU-quantity pairs, and then passed to addProductsToCart. The advantage of this approach is that no custom validation logic has to be duplicated; the same server-side checks apply as with the default Quick Order input.

For very large CSV files with several hundred or thousand rows, it is worth not sending the file as a single mutation, but splitting it into batches of, say, fifty to a hundred lines. That limits both the runtime of an individual request and the risk of a single very large request failing due to a timeout somewhere in the infrastructure between the frontend and Magento.


<?php

declare(strict_types=1);

namespace Mironsoft\QuickOrderExtension\Model;

/**
 * Splits a large list of SKU-quantity pairs into processable batches so
 * addProductsToCart is not overloaded with thousands of lines in one call.
 */
class SkuBatchSplitter
{
    private const DEFAULT_BATCH_SIZE = 75;

    /**
     * @param array<int, array{sku: string, qty: float}> $items
     * @param int $batchSize
     * @return array<int, array<int, array{sku: string, qty: float}>>
     */
    public function split(array $items, int $batchSize = self::DEFAULT_BATCH_SIZE): array
    {
        return array_chunk($items, $batchSize);
    }
}

5. Server-side SKU validation in detail

Validating a single SKU on the backend checks several things in sequence: does the SKU even exist in the product catalog, is the product visible and enabled in the current store, and in the case of a configurable product, does the entered SKU point to a concrete child variant or to the parent product, which is not directly orderable. The latter is a common source of errors in custom implementations, because customers often copy the parent SKU instead of the variant SKU from price lists.

For custom extensions that need additional SKU normalization, such as ignoring case or stripping leading zeros, a preprocessing step on the entered list before the actual mutation call is preferable, rather than changing normalization deep inside the core validation, which could collide with future B2B Suite updates.

6. Error handling: communicating partial success cleanly

Because a Quick Order request typically consists of many lines, the biggest challenge for a custom frontend is not the individual error message, but presenting a partial success in an understandable way. A user who uploads a CSV with a hundred rows and only gets told that three errors occurred can barely react meaningfully without a mapping back to the original row.

The robust solution is to carry the original CSV row index along while building the cartItems list, for example as a separate field in the internal data model, and to map the returned user_errors back to the matching original row via the affected SKU. That way the frontend can show the user exactly which row needs correction instead of just displaying a generic error count.

7. Stock and backorders during validation

Stock validation for a Quick Order line runs through the same MSI logic used elsewhere in the shop and considers the aggregated salable quantity across all assigned sources, not the stock of a single source in isolation. Whether a quantity above the current stock leads to a hard error or an accepted backorder line depends on the given product's backorder configuration.

For custom frontends it matters that a successful backorder line does not produce an error in user_errors, but typically differs in the cart through an additional delivery time notice. Anyone building a custom summary after the Quick Order process should handle that case separately, rather than showing every line without an explicit error as uniformly fully available.

8. Restricting Quick Order deliberately via plugin

For some catalogs it makes sense to exclude certain product types from fast ordering, such as virtual or downloadable products that require additional input in the normal order process that a plain SKU-quantity entry cannot represent. A plugin on the resolver or service that validates individual lines is a good fit here, adding a product type check before the actual stock and price validation.

The same mechanism can also enforce a minimum order quantity per SKU beyond the regular product configuration, for example because certain articles may only be ordered in pallet rather than unit quantities through Quick Order. It matters to use the same error channel as the default validation, so custom and default error codes can be handled uniformly in the frontend.

9. Performance with large SKU lists

For a Quick Order request with many lines, the biggest performance trap is loading price and stock data individually and sequentially per line from the database instead of using the underlying repositories' bulk loading methods. Anyone building a custom extension of the validation should consistently rely on methods that load multiple SKUs in a single call, instead of letting the number of database queries grow linearly with the list length.

For very high volumes, such as an automated nightly order from a connected ERP system, it is also worth using the same validation path as the interactive Quick Order form, but running it outside a user's synchronous request-response time, for example through a message queue consumer, so large order volumes do not slow down regular storefront traffic.

Error code Cause Behavior Frontend recommendation
PRODUCT_NOT_FOUND SKU does not exist in the catalog Line is not added Flag the row, suggest a typo check
NOT_SALABLE Stock insufficient, no backorder allowed Line is not added Report back the available quantity
INSUFFICIENT_STOCK Requested quantity exceeds stock Partial quantity or rejection depending on configuration Suggest an alternative quantity
PRODUCT_NOT_PURCHASABLE Product disabled or not visible Line is not added Filter out of future uploads
INVALID_QUANTITY Quantity is zero, negative, or malformed Line is not added Validate input format before submitting

Mironsoft

Magento development, module consulting, and system architecture

A Magento project that needs a second opinion or experienced execution?

We build custom Magento modules, advise on architecture decisions, and take on complex implementations, from service contract planning to production-ready deployment.

Architecture Consulting

Have module and system architecture thought through properly before you build.

Custom Module Development

Build custom Magento modules cleanly, following best practices.

Code Review & Audit

Have existing modules reviewed for performance, security, and maintainability.

10. Summary

Quick Order Backend API

Technical basis

Quick Order uses the same addProductsToCart mutation as other bulk cart operations.

Error handling

Invalid lines do not block valid ones, they are reported back granularly through user_errors.

CSV integration

Custom uploads can process the same mutation in batches without duplicating validation.

Performance

Bulk loading methods instead of per-SKU individual queries are decisive with large lists.

11. FAQ: Quick Order Backend API

1Is Quick Order a standalone API?
No, Quick Order is a dedicated storefront interface over the same addProductsToCart mutation also used for other bulk cart operations.
2What happens when some SKUs in the list are invalid?
Valid lines are still added to the cart, while invalid lines are reported back individually with an error code in user_errors.
3Can the same mutation be used for a custom CSV upload?
Yes, the CSV file is parsed, converted into SKU-quantity pairs, and passed to addProductsToCart, applying the same server-side validation.
4How should very large CSV files be processed?
In batches of roughly fifty to a hundred lines rather than a single mutation, to limit runtime and timeout risk.
5Why does entering a configurable product's parent SKU fail?
Because the entered SKU has to point to a concrete child variant; the parent product itself is not directly orderable through Quick Order.
6How can partial success be shown meaningfully in the frontend?
By carrying the original input's row index along and mapping the returned user_errors back to the matching row via the affected SKU.
7Does an accepted backorder line produce an error?
No, a successful backorder does not appear in user_errors, but typically differs in the cart through an additional delivery time notice.
8How can certain product types be excluded from Quick Order?
Through a plugin on the validating resolver or service that adds a product type check before the actual stock and price validation.
9What is the biggest performance trap with large SKU lists?
Loading price and stock data individually per SKU instead of through the repositories' bulk loading methods, causing the number of database queries to grow linearly.
10How can very high order volumes from an ERP system be processed sensibly?
Through the same validation path as the interactive form, but executed via a message queue consumer outside a user's synchronous response time.