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.
Table of Contents
- 1. Placing Quick Order in the B2B storefront
- 2. The flow: from SKU list to cart
- 3. The underlying GraphQL mutation
- 4. Building custom CSV upload frontends
- 5. Server-side SKU validation in detail
- 6. Error handling: communicating partial success cleanly
- 7. Stock and backorders during validation
- 8. Restricting Quick Order deliberately via plugin
- 9. Performance with large SKU lists
- 10. Summary
- 11. FAQ
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.