Ad-Hoc Products
Published by Todd Menier on June 21, 2022
Last updated on May 16, 2023
OrderCloud provides a robust set of features for creating, organizing, and presenting product catalogs. For most, OrderCloud is not the master record for such data, and a significant effort is required to keep this data synchronized. But in a smaller subset of cases, sellers are already equipped not just with back-office product data but with full browsing and search capabilities for their buyers. All they need from OrderCloud are purchasing and order management capabilities. In these cases, an integrator can leverage OrderCloud's Ad-Hoc Products feature to provide product data on demand and skip the cumbersome catalog synchronization effort entirely. Let's take a look at how it works.
The AddToCart
Integration Event
The first step in integrating an external product catalog with OrderCloud orders is implementing an HTTP service that provides product data via a well-defined RESTful API. Specifically, OrderCloud has defined a new Integration Event type: AddToCart
. Once defined and assigned to an ApiClient
via the AddToCartIntegrationEventID
property, whenever a Buyer User adds a line item to an unsubmitted order, OrderCloud will send a POST
request to the configured endpoint with a payload like the following:
1{2 "ProductID": "XYZ-123",3 "Quantity": 2,4 "BuyerID": "BUYER-X",5 "BuyerUser": { ... },6 "SellerID": "SELLER-Y",7 "Environment": "Production",8 "OrderCloudAccessToken": "6MNTg0TM3Cwi...",9 "ConfigData": { }10}
ProductID
and Quantity
are what you'll typically use to look up the product and its price in the external system; other fields are provided mostly for authentication and identification purposes. BuyerUser
contains all the same fields as the response of a buyer user GET request.
Your configured endpoint is expected to return an HTTP 200 response with a body like the following:
1{2 "Product": {3 "ID": "XYZ-123",4 "Name": "My Ad-Hoc Product",5 "Description": "blah blah blah",6 "QuantityMultiplier": 1,7 "ShipWeight": 123,8 "ShipHeight": 456,9 "ShipWidth": 123,10 "ShipLength": 456,11 "DefaultSupplierID": null,12 "Returnable": false,13 "xp": { }14 },15 "UnitPrice": 9.9916}
Most Product
fields are optional and are in fact validated in much the same way as creating a new cataloged product in terms of required fields, max string lengths, etc.
If the requested product is not found in the external system, the appropriate response from your endpoint is still HTTP 200, but with the Product
object set to null
. This will result in a 404 response from OrderCloud with an error code signaling that the product was not found. However, any response in the 4xx or 5xx range (inlcuding 404) returned from your endpoint is interpreted as a misconfigured integration event and results in a 400 response from OrderCloud. This ensures that OrderCloud can distinguish between a missing product and a missing or misconfigured service endpoint.
A non-null UnitPrice
is required, but only when Product
is not null.
Synchronizing Products on Unsubmitted Orders
As described, ad-hoc products are captured directly on orders by handling the AddToCart
event. And it is well understood that in any scenario, a snapshot of product data is captured on order submit, and is no longer subject to changes to the "live" product. But this creates a gap in the ad-hoc case: how do you synchronize changes in the external system with those products on unsubmitted orders?
In keeping with the "on-demand" nature of ad-hoc products, we've enhanced our Order Checkout integration event to support this scenario. Specifically, the Order Calculate step now allows you to (optionally) return a Product
object as part of its LineItemOverrides
collection. This can be a partial representation, and behaves much like a PATCH
operation on the ad-hoc product. Also provided is the Remove
property (also optional), which can be set to true
to indicate that the line item should be silently removed from the unsubmitted order. This is consistent with what happens automatically when an OC-cataloged product becomes unavailable.
For completeness, here's a look at an Order Calculate response with all LineItemOverrides
fields included (only LineItemID
is required):
1{2 "LineItemOverrides": [3 {4 "LineItemID": "SampleLineItemID",5 "Product": { },6 "UnitPrice": 6.00,7 "PromotionOverrides": [],8 "Remove": false9 },10 ...11 ]12}
Still have questions?
Ask in our Community Channel