Catalog API Documentation
Browse endpoints, parameters, and live request examples.
Cart Management
Complete guide to building, managing, and converting shopping carts to orders
Cart Management Flow
The cart system provides a complete shopping experience from product selection to order placement.
Each cart is uniquely identified by the combination of a
socket_id
and an
external_user_id
that you provide.
This means each user can have one cart per socket, allowing different product selections for different catalogs.
Items from one socket's catalog cannot be mixed with items from another socket's catalog. Each cart is isolated to its specific socket.
Only items that exist in the socket's catalog can be added to that socket's cart.
When you add multiple units of the same product, each unit becomes a separate line item in the cart. While you can display these as a quantity to your end users (e.g., "3x Widget"), the API treats each as an individual line item. This approach makes order management much easier, since you can see individually cancelled items, view partial shipments, process partial refunds, and track fulfillment status per item without complex quantity calculations.
Cart Isolation: A user shopping in Socket A cannot add items from Socket B to their Socket A cart. If the same user needs items from multiple sockets, they must maintain separate carts and place separate orders for each socket.
Typical Cart Flow
1 Add Items to Cart
Use POST /sockets/{socket_id}/cart/{external_user_id} to add products. The cart is automatically created if it doesn't exist.
{
"items": [
{
"catalog_item_id": 12345,
"line_item_id": "custom-id-123",
"metadata": {
"cost_center": "WEf333-001",
"manager_id": "2938749823670"
}
}
]
}
Returns: Cart with new item, updated totals, and new
cart_version
2 Modify Cart Contents
Update line item metadata: PUT /sockets/{socket_id}/cart/{external_user_id}/line_items/{line_item_id}
Used to save information you can use later in the order track call.
Remove items: DELETE /sockets/{socket_id}/cart/{external_user_id}/line_items/{line_item_id}
Removes specific line items while preserving the rest of the cart.
3 Set Cart-Level Metadata
Use PUT /sockets/{socket_id}/cart/{external_user_id}/metadata for order-level information:
- A group in your application the user belongs to
- Special instructions to our accounting system indicating what account you will be paying with
- Any user detail you wish to show on extract data from our systems.
Note: Metadata must be flat key-value pairs with string values only. Nested objects are not supported.
4 Set Shipping Address
Use POST /sockets/{socket_id}/cart/{external_user_id}/set_address to provide delivery details:
{
"first_name": "John",
"last_name": "Doe",
"address_1": "123 Main St",
"city": "New York",
"state": "NY",
"postal_code": "10001",
"country": "US",
"email": "john@example.com",
"phone": "555-0123"
}
5 Validate & Lock Cart
Use POST /sockets/{socket_id}/cart/{external_user_id}/validate to:
- Verify all items are still available
- Confirm prices haven't changed
- Reserve stock for limited items
- Lock the cart to prevent modifications
Success:
Cart is locked and ready for order placement. Save the returned
cart_version
for the final step.
6 Convert to Order
Use
POST /sockets/{socket_id}/cart/{external_user_id}/order_place
with the locked cart version.
You must provide a unique
external_order_id
for each order you create - this ID must be distinct across all orders in your account and will be used for tracking and reconciliation.
{
"cart_version": "abc123-def456", // From validate response
"external_order_id": "ORD-2024-001", // Must be unique across your account
"line_item_payments": [
{
"line_item_id": "d872cb2d-f847-4304-a697-44a5c639b22e",
"price_paid": "29.99"
}
]
}
Returns: Order confirmation with tracking number
Version Control:
Each operation returns a
cart_version
that ensures safe concurrent operations. Always use the version returned from your validation call to place the order.
Understanding Cart Versions
Cart versions are critical for preventing race conditions and ensuring data consistency. Each cart modification returns a new version UUID that represents the cart's current state. When placing an order, the version ensures the cart hasn't been modified since validation, preventing issues like:
- Double-charging if users click "Place Order" multiple times
- Order placement with outdated prices or unavailable items
- Conflicts when multiple sessions access the same cart
- Race conditions between cart updates and order placement
Critical:
Always pass the
cart_version
from the validate response to order_place. If the versions don't match, the order will be rejected,
and you'll need to unlock and re-validate the cart.
Why validate Rejects a Cart
Validation runs a set of pre-flight checks before we accept an order. It is the most common place integration bugs surface, and the most important call to make before every order. These are the rejections you will actually see.
Stale prices
The price of one or more items has changed since they were added. Re-read the cart, show the user the new totals, and let them re-confirm before retrying validate and order.
Out of stock or unavailable
An item that was available when added is no longer available. Remove it, or let the user choose an alternative, and revalidate. Do not hide the error. Users would rather know before they try to check out.
Address missing or invalid
You need to set the cart address before validate. If you already did and it still fails, the address failed supplier validation. That is usually a typo in the postal code, or a PO box for an item that cannot ship to one.
Region mismatch
Some items cannot ship to the address's country or region. The error response identifies which line items are affected, so you can remove them or change the shipping address.
Cart version conflict
You passed a stale cart_version, meaning another
request already modified the cart. Re-read the cart, which returns the current
version, then retry.
Every validate failure includes error.code
and error.details
in the response body, identifying exactly which line items and fields triggered it.
Show that structured error to the user rather than a generic failure message.
Address Field Limits
The API does not impose a strict maximum length on address fields, but the fulfillment system that receives your orders stores each field in a fixed-width column. A value longer than the column can get the order rejected, or the field truncated downstream, so keep address fields within these lengths.
| Field | Max characters |
|---|---|
given_name
|
60 |
surname
|
60 |
address_1
(required)
|
75 |
address_2
|
60 |
address_3
|
60 |
address_4
|
60 |
city
(required)
|
60 |
state_or_region
|
60 |
postal_code
(required)
|
15 |
country
(required)
|
2 (ISO 3166-1 alpha-2 code) |
phone_number
|
255 |
email
|
255 |
Put the meaningful street address in address_1
through address_4. If a value regularly runs long,
abbreviate it before sending, for example "Apt" instead of "Apartment", rather than
relying on truncation.
Error Recovery
Cart is Locked
If validation succeeded but order placement failed, use POST /sockets/{socket_id}/cart/{external_user_id}/unlock to release the lock and reserved stock.
Stock Availability Changed
For limited stock items, use POST /sockets/{socket_id}/cart/{external_user_id}/line_items/{line_item_id}/revalidate_stock to check current availability.
Clear Cart
To start over, use POST /sockets/{socket_id}/cart/{external_user_id}/empty to remove all items at once.
Best Practices
- Always use the latest cart_version when modifying carts
- Implement retry logic with exponential backoff for network failures
- Store cart_version client-side to detect concurrent modifications
- Validate carts before payment processing, not after
- Use metadata for any custom business logic or tracking needs
- Set reasonable timeouts for locked carts (typically 5-10 minutes)