Learn how to prevent overselling and improve the checkout experience by automatically reserving items in a Cart.
In this tutorial, you will learn how to temporarily reserve products for a customer, giving them time to complete their checkout. By the end, you will have created a Cart with reserved Line Items and will understand how to manage these reservations.
You will learn to:
- Create a Cart that automatically reserves items.
- Extend the duration of a reservation.
- Understand and handle different reservation-related warnings.
Prerequisites
Before you begin, you should be familiar with:
- Composable Commerce concepts such as Products, Carts, and Inventory.
- Using a REST API client such as Postman or Insomnia to interact with the Composable Commerce API.
- General concepts around Project setup and API Client management in the Merchant Center.
- A Product: Create a Product with at least one Product Variant. Note the
SKUof the variant. - API Client: An API Client with the following scopes:
manage_orders:{projectKey}to create and update Carts and Orders.manage_project_settings:{projectKey}to update reservation-related Project settings.manage_products:{projectKey}to create and update Inventory Entries.
Instructions
The following instructions walk through creating and managing stock reservations. The scenario follows a customer who adds a popular, limited-stock item to their cart. To ensure they have a chance to purchase it, the item is reserved for them for a limited time.
Set the Project-level expiration
ReserveOnCart InventoryMode, which automatically reserves Line Items when they are added to the Cart.This is a mandatory step to ensure that stock is not held indefinitely, which could lead to it being unavailable for other customers. You only have to set this once per Project.
This value will be the fallback for any inventory entry that doesn't have a specific expiration set.
The next section covers how to create a reservation and override the Project-level reservation expiration time for individual SKUs.
Create a reservation
First, create a Cart with a product to be reserved.
Create an Inventory Entry
SKU-1 in this example) with stock available. In this example, reservationExpirationInMinutes is set to 30 minutes. If you omit this value, the Project-level default will be used.reservationExpirationInMinutes values must be at least 1 minute and at most 44640 minutes (31 days).curl -X POST "https://api.europe-west1.gcp.commercetools.com/{{project-key}}/inventory" \
-H "Authorization: Bearer {{auth-token}}" \
-H "Content-Type: application/json" \
-d '{
"sku": "SKU-1",
"quantityOnStock": 10,
"reservationExpirationInMinutes": 30
}'
Create a Cart
inventoryMode to ReserveOnCart, you instruct commercetools to create a reservation for all the Line Items in the Cart.inventoryMode for each Line Item, allowing for mixed reservation behaviors within a single Cart.curl -X POST "https://api.europe-west1.gcp.commercetools.com/{{project-key}}/carts" \
-H "Authorization: Bearer {{auth-token}}" \
-H "Content-Type: application/json" \
-d '{
"currency": "USD",
"inventoryMode": "ReserveOnCart",
"lineItems": [
{
"sku": "SKU-1",
"quantity": 1
}
]
}'
SKU-1. The reservation expiration time is the same one that was set in the associated Inventory Entry. In this case, the reservation is valid for 30 minutes.availableQuantity for this SKU is reduced by 1, while quantityOnStock remains unchanged until the Order is placed. This change is eventually consistent and may take up to 10 seconds to appear. For more details, see Inventory checks and consistency.Verify the reservation
reservation field on the Line Item, containing a reference to the created Reservation object. The absence of any warnings is also a good indicator that everything worked as expected.{
"lineItems": [
{
"id": "...",
"productId": "...",
"name": { "...": "..." },
"variant": { "...": "..." },
"quantity": 1,
"reservation": {
"typeId": "reservation",
"id": "..."
}
}
],
"inventoryMode": "ReserveOnCart",
"warnings": []
}
Extend a reservation
Cart interactions can be complex. Payments might fail or additional validation steps can delay checkout. To prevent a reservation from expiring while the customer is completing their purchase, you can extend its duration.
Extend the reservation
curl -X POST "https://api.europe-west1.gcp.commercetools.com/{{project-key}}/carts/{{cart-id}}" \
-H "Authorization: Bearer {{auth-token}}" \
-H "Content-Type: application/json" \
-d '{
"version": 1,
"actions": [
{
"action": "setReservationExpirationInMinutes",
"reservationExpirationInMinutes": 30
}
]
}'
Reservation object, setting its expiration time to 30 minutes from now.Verify the extension
reservation field remains present. To see the details, you can expand the reservation reference.Handle reservation warnings
When creating or updating a Cart, a reservation can potentially fail. When this happens, commercetools ensures that the Cart remains orderable by adjusting its contents and provides a warning for each failure.
The behavior depends on whether you are creating or updating a Cart:
- When creating a Cart, if all Line Items with
inventoryMode: "ReserveOnCart"fail to be reserved, the entire operation fails with a400 Bad Request(InvalidOperation) error. If only some items fail, the Cart is created, but the failed Line Items are removed from it and mentioned in a warning (see Scenario 1). - When updating a Cart, if a reservation update for a Line Item cannot be fulfilled (for example, when increasing its quantity), a warning is added to the response (see Scenario 2) and the quantity is not updated.
In all cases of partial success or adjustment, a warning is added to the response. This gives you the information needed to create the experience you want for your customers, like notifying them about the changes in their Cart.
The following diagram summarizes the different reservation scenarios:
Scenario 1: CannotCreateReservation
ReserveOnCart is added to a Cart, but the reservation fails due to lack of stock. When this happens, the Line Item is not added to the Cart, ensuring the Cart remains orderable.Create a Cart with two Line Items. One with a quantity that can be fulfilled, and another with a quantity greater than its availability.
{
"warnings": [
{
"code": "CannotCreateReservation",
"message": "Failed to create a reservation for product 987fcdeb-51a2-43d1-9c4f-123456789abc (SKU: SAMPLE-SKU-001, Supply Channel: channel-123) with quantity 5.",
"productId": "987fcdeb-51a2-43d1-9c4f-123456789abc",
"sku": "SAMPLE-SKU-001",
"supplyChannel": "channel-123",
"quantity": 5
}
]
}
Scenario 2: CannotUpdateReservation
This warning is returned when you update a Line Item's quantity, but the reservation cannot be updated to match the new quantity. This is usually due to insufficient stock. The quantity of the Line Item remains the same.
- Ensure
SKU-1has a stock of 5. - Create a Cart with
SKU-1,quantity: 2, andinventoryMode: "ReserveOnCart". A reservation for 2 items is created.- Available quantity: 5 (initial) - 2 (reserved) = 3
- Update the Cart to change the quantity of the Line Item to 6 (that is, adding 4 more items). This requires 4 additional items to be reserved, but only 3 are available. The reservation update fails, and the Line Item quantity in the Cart remains at 2 (the original quantity).
- Available quantity: 3. Additional items requested: 4. Reservation update fails.
{
"warnings": [
{
"code": "CannotUpdateReservation",
"message": "Failed to update the reservation for line item 123e4567-e89b-12d3-a456-426614174000 (Product ID: 987fcdeb-51a2-43d1-9c4f-123456789abc, SKU: SAMPLE-SKU-001, Supply Channel: channel-123) to a quantity of 6. The reserved amount is still 2.",
"lineItemId": "123e4567-e89b-12d3-a456-426614174000",
"requestedQuantity": 6,
"reservedQuantity": 2,
"productId": "987fcdeb-51a2-43d1-9c4f-123456789abc",
"sku": "SAMPLE-SKU-001",
"supplyChannel": "channel-123"
}
]
}
Scenario 3: CannotChangeReservationExpiry
This warning appears if you try to extend a reservation that has already expired or is in a state that doesn't allow extension.
- Use the Set Reservation Expiration In Minutes update action on the Inventory Entry and specify a short duration, for example, 1 minute.
- Create a Cart with
SKU-1andinventoryMode: "ReserveOnCart". - Wait for the reservation to expire.
- Try to extend the Cart's reservations using the Set Reservation Expiration in Minutes update action on the Cart.
{
"warnings": [
{
"code": "CannotChangeReservationExpiry",
"message": "The reservation expiration for line item 448085fc-fe34-484a-8d77-ad6b9148ef59 cannot be changed.",
"lineItemId": "448085fc-fe34-484a-8d77-ad6b9148ef59"
}
]
}
Summary
You have learned how to:
- Use the
ReserveOnCartinventory mode to create temporary stock reservations. - Extend reservations to give customers more time to check out.
- Understand and handle warnings related to reservation mismatches and expirations.
This feature helps improve the customer experience for high-demand products by providing a fair window for purchase. When implementing this in a real project, remember to build user-facing notifications for the various warning scenarios to keep your customers informed.
Further reading
To learn more about implementing reservations, see the following resources:
-
Reserve stock on demand and freeze prices: prevent overselling by reserving items on demand while freezing prices.
-
Inventory overview: information about managing inventory, reservations, and stock levels.