Add Line Item
POST https://api.firmly.work/api/v2/domains/{domain}/cart/line-items
Overview
The Add Line Item endpoint adds a new product to the shopping cart with these features:
- Automatic Shipment Assignment: Once a shipping address is set, items are automatically grouped into shipments based on their fulfillment requirements — see Shipping & Fulfillment
- Catalog Integration: Uses
add_to_cart_refobject directly from catalog API responses - Variant Support: Handles configurable products with variant handles
- Cart Creation: Automatically creates a new cart if one doesn’t exist
- Optional Cart Clearing: Can clear existing cart before adding new item
Authentication
x-firmly-authorization(string, required) — Device access token from Browser Session
Path Parameters
domain(string, required) — Domain of the merchant website (e.g.,staging.luma.gift)
Query Parameters
flush_cart(string"true"|"false", default"false") — When"true", clears the cart before adding the new item. This is a string, not a boolean — only the exact lowercase strings"true"/"false"are accepted; any other value (1,0,True, empty string) returns400 InvalidInputQueryrather than being treated as falsy.
Request Body
-
add_to_cart_ref(object, required) — Product reference from catalog API containing variant information Properties:variant_id(string, required): Product variant identifierproduct_id(string, optional): Parent product identifiervariant_handles(array, optional): Array of variant configuration handles (e.g.,["color:blue", "size:large"])
-
quantity(integer, required) — Quantity to add (minimum 1). Numeric strings (e.g."2") are also accepted and coerced to a number.
Response
Returns the complete shopping cart including the newly added item. See Get Cart for full response schema.
Key Response Features:
-
shipments(array) — Empty until a shipping address is set. Shipment grouping is populated by Set Shipping Info. -
addons.offers(array) — Available addon services for the updated cart. Offer fields such ascoverage_mode,eligible_line_item_ids, andchild_offersare documented in Addon Management. -
schema_version(string) — Indicates the cart schema version
Code Examples
curl --request POST \--url https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/line-items \--header 'Content-Type: application/json' \--header 'x-firmly-authorization: YOUR_TOKEN' \--data '{"add_to_cart_ref": {"variant_id": "WS12-XS-Orange"},"quantity": 1}'
const response = await fetch('https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/line-items', {method: 'POST',headers: {'Content-Type': 'application/json','x-firmly-authorization': 'YOUR_TOKEN'},body: JSON.stringify({add_to_cart_ref: {variant_id: 'WS12-XS-Orange'},quantity: 1})});const cart = await response.json();console.log(cart);
import requestsresponse = requests.post('https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/line-items',headers={'Content-Type': 'application/json','x-firmly-authorization': 'YOUR_TOKEN'},json={'add_to_cart_ref': {'variant_id': 'WS12-XS-Orange'},'quantity': 1})cart = response.json()print(cart)
<?php$curl = curl_init();$data = ['add_to_cart_ref' => ['variant_id' => 'WS12-XS-Orange'],'quantity' => 1];curl_setopt_array($curl, [CURLOPT_URL => "https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/line-items",CURLOPT_RETURNTRANSFER => true,CURLOPT_POST => true,CURLOPT_HTTPHEADER => ["Content-Type: application/json","x-firmly-authorization: YOUR_TOKEN"],CURLOPT_POSTFIELDS => json_encode($data)]);$response = curl_exec($curl);curl_close($curl);$cart = json_decode($response, true);print_r($cart);?>
Advanced Examples
With Variant Handles
For configurable products with multiple options:
{"add_to_cart_ref": {"variant_id": "MH07-XS-Gray","variant_handles": ["color:gray", "size:xs"]},"quantity": 1}
Clear Cart First
To replace cart contents with a new item:
curl --request POST \--url 'https://api.firmly.work/api/v2/domains/staging.luma.gift/cart/line-items?flush_cart=true' \--header 'Content-Type: application/json' \--header 'x-firmly-authorization: YOUR_TOKEN' \--data '{"add_to_cart_ref": {"variant_id": "WT09-XS-White"},"quantity": 2}'
Catalog Integration
The add_to_cart_ref object should be passed directly from catalog API responses:
{"products": [{"product_id": "WS12","variants": [{"add_to_cart_ref": {"variant_id": "WS12-XS-Orange","variant_handles": ["color:orange", "size:xs"]}}]}]}
{"add_to_cart_ref": {"variant_id": "WS12-XS-Orange","variant_handles": ["color:orange", "size:xs"]},"quantity": 1}
Response Example
{"line_items": [{"line_item_id": "9b13b973-8d55-5d00-b22a-1b1b788d80f9","platform_line_item_id": "0","sku": "WS12-XS-Orange","variant_description": "Color: Orange, Size: XS","description": "Radiant Tee","base_sku": "WS12","quantity": 1,"price": {"currency": "USD","value": 22.00,"number": 2200,"symbol": "$"},"line_price": {"currency": "USD","value": 22.00,"number": 2200,"symbol": "$"},"msrp": {"currency": "USD","value": 22.00,"number": 2200,"symbol": "$"},"image": {"url": "https://cdn.staging.luma.gift/product/radiant-tee-orange.jpg","alt": "Radiant Tee in Orange","type": "default"},"requires_shipping": true}],"shipments": [],"sub_total": {"currency": "USD","value": 22.00,"number": 2200,"symbol": "$"},"shipping_total": {"currency": "USD","value": 0,"number": 0,"symbol": "$"},"tax_total": {"currency": "USD","value": 0,"number": 0,"symbol": "$"},"fees": [{"description": "Recycle fee","currency": "USD","value": 2.00,"number": 200,"symbol": "$"}],"fee_total": {"currency": "USD","value": 2.00,"number": 200,"symbol": "$"},"total": {"currency": "USD","value": 24.00,"number": 2400,"symbol": "$"},"addons": {"offers": [{"addon_id": "protection-new-item-12345","display": {"name": "Product Protection Plan"},"price": {"currency": "USD","value": 0,"number": 0,"symbol": "$"},"scope": "ITEM","coverage_mode": "PER_ITEM","eligible_line_item_ids": ["9b13b973-8d55-5d00-b22a-1b1b788d80f9"],"child_offers": [{"addon_id": "A0-FURN-2y","display": {"name": "2 Year Protection"},"scope": "INHERIT","coverage_mode": "PER_ITEM","eligible_line_item_ids": ["9b13b973-8d55-5d00-b22a-1b1b788d80f9"],"price": {"currency": "USD","value": 149.99,"number": 14999,"symbol": "$"}},{"addon_id": "A0-FURN-3y","display": {"name": "3 Year Protection"},"scope": "INHERIT","coverage_mode": "PER_ITEM","eligible_line_item_ids": ["9b13b973-8d55-5d00-b22a-1b1b788d80f9"],"price": {"currency": "USD","value": 199.99,"number": 19999,"symbol": "$"}}]}],"selections": []},"addon_total": {"currency": "USD","value": 0,"number": 0,"symbol": "$"},"schema_version": "2.0"}
Related Endpoints
- Get Cart — View current cart state
- Update Line Item — Modify cart items
- Clear Cart — Empty the cart
Error Responses
Errors return a JSON body with code, error, and description. Program against the error value — descriptions are human-readable and may change.
400 — MissingAuthHeader
The x-firmly-authorization header is missing or empty.
{"code": 400,"error": "MissingAuthHeader","description": "x-firmly-authorization header is missing or invalid."}
400 — InvalidToken
The authorization token is not a valid JWT structure.
{"code": 400,"error": "InvalidToken","description": "Jwt token is invalid."}
400 — InvalidAPIToken
The API token (server-to-server secret) is invalid or has been revoked.
{"code": 400,"error": "InvalidAPIToken","description": "API token is invalid."}
400 — BadRequest
Server-to-server auth was attempted but the required headers (x-firmly-authorization plus x-firmly-device-id) are missing or malformed.
{"code": 400,"error": "BadRequest","description": "Bad request."}
401 — Unauthorized
The authorization token was rejected.
{"code": 401,"error": "Unauthorized","description": "Unauthorized."}
401 — InvalidJWTToken
The device JWT signature does not verify, or required claims are missing.
{"code": 401,"error": "InvalidJWTToken","description": "Jwt token is invalid."}
404 — PartnerNotFound
The appid claim on the device JWT does not map to a known partner / tenant — typically a token from a different environment.
{"code": 404,"error": "PartnerNotFound","description": "Partner not found."}
404 — DomainNotFound
The {domain} path parameter does not match any merchant configured with Firmly, or the merchant has been disabled. Verify the domain string (case-sensitive, no protocol or trailing slash).
{"code": 404,"error": "DomainNotFound","description": "This domain was not found in firmly servers."}
404 — ProductNotFound
The variant_id supplied in add_to_cart_ref does not exist in the merchant catalog. Refresh from the Catalog API and retry with a current ID.
{"code": 404,"error": "ProductNotFound","description": "Product not found."}
409 — NotEnoughStockError
The requested quantity exceeds available inventory for the variant. Reduce quantity or wait for restock.
{"code": 409,"error": "NotEnoughStockError","description": "Not enough stock."}
409 — CannotCreateCart
The merchant system rejected creation of a new cart. Often transient — retry; if it persists, check merchant system health.
{"code": 409,"error": "CannotCreateCart","description": "Cannot create cart."}
412 — ProductNotSupported
The product type is not supported by this merchant’s adapter (e.g. some adapters reject gift cards, digital-only SKUs, or subscription items).
{"code": 412,"error": "ProductNotSupported","description": "Product is not supported."}
412 — PostalCodeRequired
The merchant requires a postal code before items can be added. Call Set Postal Code, then retry.
{"code": 412,"error": "PostalCodeRequired","description": "Postal code is required."}
412 — OperationNotSupported
The merchant’s platform does not support this operation. Some platform adapters do not implement every cart operation; check with Firmly whether this endpoint is available for the merchant.
{"code": 412,"error": "OperationNotSupported","description": "This operation is not supported for this store."}
412 — NoLineItemError
The merchant accepted the request but did not return a line item — typically indicates a product was silently rejected by merchant validation. Verify the variant is purchasable and try again.
{"code": 412,"error": "NoLineItemError","description": "No line item."}
400 — InvalidInputBody
Request body is missing required fields or fails schema validation. Ensure add_to_cart_ref.variant_id and quantity are present and quantity >= 1.
{"code": 400,"error": "InvalidInputBody","description": "The body is not processable"}