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)