Update cart

Update an existing cart by session ID or hash. If a valid session ID is passed, the cart will be updated for the session user. If the session ID is invalid, a cart will be retrieved and updated by the JWT.

Request Parameters

🏷️ header · unmarked parameters are query params

ParameterTypeRequiredDescription
Locally-Api-Token 🏷️stringYesLocally API token must be passed in the header to authenticate the API consumer.
Locally-Api-Session-Id 🏷️stringYesSession ID must be passed in the header to persist the user session. Can expire.
Locally-Pl-Jwt 🏷️stringNoJSON Web Token passed in the header to identify the user. Does not expire.
qty[{{ITEM_ID}}]arrayNoQuantity of a specific item in the order. The parameter is an array of item IDs and quantities. Example: qty[123]=2,qty[456]=3.
remove_itemintegerNoItem ID to remove.
host_domainstringNoThe domain from which the request is being made.

Example Request

curl 'https://www.locally.com/headless/api/1.0/cart' \
--request POST \
--header 'Locally-Api-Token: {{API_TOKEN}}' \
--header 'Locally-Api-Session-Id: {{SESSION_ID}}' \
--header 'Locally-Pl-Jwt: {{CART_HASH_JWT}}' \
--url-query 'qty[{{ITEM_ID}}]=2' \
--url-query 'host_domain=www.example.com'
const response = await fetch(
  'https://www.locally.com/headless/api/1.0/cart?qty[{{ITEM_ID}}]=2&host_domain=www.example.com',
  {
    method: 'POST',
    headers: {
      'Locally-Api-Token': '{{API_TOKEN}}',
      'Locally-Api-Session-Id': '{{SESSION_ID}}',
      'Locally-Pl-Jwt': '{{CART_HASH_JWT}}'
    }
  }
);

const data = await response.json();
import requests

response = requests.post(
    'https://www.locally.com/headless/api/1.0/cart',
    params={
        'qty[{{ITEM_ID}}]': 2,
        'host_domain': 'www.example.com'
    },
    headers={
        'Locally-Api-Token': '{{API_TOKEN}}',
        'Locally-Api-Session-Id': '{{SESSION_ID}}',
        'Locally-Pl-Jwt': '{{CART_HASH_JWT}}'
    }
)

data = response.json()

The qty parameter is keyed by cart item ID — found at data.cart_content.cart.items[].id in any cart response — and sets that item's new quantity. To remove an item entirely, pass remove_item with the item ID instead of qty. The Locally-Pl-Jwt header is optional but recommended: if the session ID has expired, the cart is retrieved and updated by the JWT.

Example Response

{
    "success": true,
    "data": {
        "n_in_cart": 1,
        "cart_hash": "QE3QL6",
        "cart_content": {
            "user": {
                "id": 999,
                "email": "[email protected]",
                "first_name": "",
                "last_name": "",
                "phone": "",
                "preferred_zip": "60605",
                "preferred_country": "US"
            },
            "cart": {
                "id": 999,
                "user_id": 999,
                "hash": "QE3QL6",
                "subtotal": 200,
                "tax_total": 20.5,
                "shipping_cost_total": 0,
                "grand_total": 220.5,
                "first_name": "",
                "last_name": "",
                "address": "",
                "address_2": "",
                "city": "",
                "state": "",
                "zip": "",
                "email": "",
                "phone": "",
                "country": "",
                "locale": "en-us",
                "origin": "www.example.com",
                "for_hold": 0,
                "for_delivery": 0,
                "delivery_first_name": "",
                "delivery_last_name": "",
                "delivery_address": "",
                "delivery_address_2": "",
                "delivery_city": "",
                "delivery_state": "",
                "delivery_zip": "",
                "delivery_country": "",
                "delivery_fee_total": 0,
                "is_test": 0,
                "delivery_choice": "",
                "store_delivery_fee": 0,
                "delivery_notes": "",
                "coupon_discount_total": 0,
                "coupon_code": "",
                "coupon_discount_reason": "",
                "for_ship_to_store": 0,
                "cart_currency": "USD",
                "items": [
                    {
                        "id": 999,
                        "qty": 2,
                        "upc": "000000000000",
                        "product_name": "ACME Outfitters Widget",
                        "product_company_name": "ACME Outfitters",
                        "product_image": "image.jpg",
                        "product_color": "Red",
                        "product_size": "M",
                        "product_price": 100,
                        "product_id": 999999,
                        "store_id": 99999,
                        "subtotal": 200,
                        "tax_total": 20.5,
                        "shipping_cost": 0,
                        "grand_total": 220.5,
                        "qty_available": 10,
                        "message": "",
                        "fulfillment_type": 0,
                        "product_currency": "USD",
                        "product_company_id": 999,
                        "coupon_discount_total": 0,
                        "vat": 0,
                        "tax_rate": 10.25,
                        "product": {
                            "id": 999999,
                            "name": "ACME Outfitters Widget",
                            "company_id": 999,
                            "style_number": "99999",
                            "image": "image.jpg",
                            "long_description": "Lorem ipsum.",
                            "average_rating": 5,
                            "n_reviews": 1,
                            "upc_data": null,
                            "company": null
                        }
                    }
                ],
                "custom_cart_text": ""
            },
            "country": {
                "id": 99,
                "name": "United States",
                "code": "US",
                "primary_currency": "USD",
                "secondary_currency": "",
                "primary_locale": "en-us",
                "phone_prefix": "1",
                "display_marketing_consent": "",
                "consent_checkbox_default_state": 0,
                "code_3": "USA",
                "display_brand_marketing_consent": ""
            },
            "cart_error": 0,
            "cart_disclaimer": "By continuing you agree to our <a href=https:\/\/www.locally.com\/terms target=_blank>terms of service<\/a>",
            "cart_store": {
                "id": 99999,
                "name": "ACME Outfitters Chicago",
                "address": "123 ACME St.",
                "zip": "00000",
                "company_id": 999,
                "lat": "41.91136867",
                "lng": "-87.67771437",
                "phone": "(312) 555-0142",
                "mon_time_open": 1100,
                "mon_time_close": 1900,
                "tue_time_open": 1100,
                "tue_time_close": 1900,
                "wed_time_open": 1100,
                "wed_time_close": 1900,
                "thu_time_open": 1100,
                "thu_time_close": 1900,
                "fri_time_open": 1100,
                "fri_time_close": 1900,
                "sat_time_open": 1100,
                "sat_time_close": 1900,
                "sun_time_open": 1100,
                "sun_time_close": 1700,
                "address_2": "",
                "city": "Chicago",
                "state": "IL",
                "country": "US",
                "timezone": "America\/Chicago",
                "average_rating": 5,
                "n_reviews": 3,
                "image": "image.jpg",
                "web_address": "https:\/\/www.example.com",
                "is_temporarily_closed": 0,
                "area": null,
                "store_hours": [
                    {
                        "id": 1,
                        "store_id": 99999,
                        "type": 0,
                        "custom_label": null,
                        "dow": 0,
                        "single_day": null,
                        "closed": 0,
                        "start_time": 700,
                        "end_time": 2000,
                        "group": 1,
                        "is_closed": 0
                    },
                    {
                        "id": 2,
                        "store_id": 99999,
                        "type": 0,
                        "custom_label": null,
                        "dow": 1,
                        "single_day": null,
                        "closed": 0,
                        "start_time": 700,
                        "end_time": 2000,
                        "group": 1,
                        "is_closed": 0
                    }
                ],
                "pickup_time_slots": {
                    "time": null,
                    "days": null
                },
                "store_vat_details": {
                    "id": 99999,
                    "uses_vat": 0,
                    "sales_tax_label": ""
                },
                "acquisition_options": {
                    "bopis": 1,
                    "sdd": 1,
                    "ropis": 1
                }
            }
        },
        "delivery_options": null,
        "delivery_unavailable_reason": null,
        "session": {
            "id": "vD2kq9mXw4bT7nR5cJ1sL8fA3gH6pZ0yE2uN4iK9"
        }
    },
    "msg": ""
}
{
    "success": false,
    "data": {
        "cart_hash": "QE3QL6",
        "cart_content": {
            "cart_error": "Sorry, this purchase option is no longer available at this store."
        },
        "session": {
            "id": "vD2kq9mXw4bT7nR5cJ1sL8fA3gH6pZ0yE2uN4iK9"
        }
    },
    "msg": ""
}

Response Explanation

  • successtrue for a healthy cart. Cart-level failures still return HTTP 200 with success: false and the reason in data.cart_content.cart_error; other failures use HTTP 4xx/5xx with msg and error_code.
  • data.n_in_cart — Count of distinct line items in the cart, not the summed quantity — a single item with qty: 2 still returns n_in_cart: 1.
  • data.cart_hash — The cart's permanent short identifier, identical to data.cart_content.cart.hash. Use it as the hash parameter when placing the order.
  • data.cart_content.cart.items[].id — Cart item line ID — the {{ITEM_ID}} key for Update cart's qty array and its remove_item parameter. Removal only works before the item is ordered (Cart Item Statuses).
  • data.cart_content.cart.items[].qty_available — The store's current on-hand stock for this UPC, capped by any brand per-order quantity limit. Quantity updates above this value are silently ignored.
  • data.cart_content.cart.items[].fulfillment_type — How the line is fulfilled: 0 pickup, 10 delivery, 20 ship-to-store. 99 is an internal marker for Stripe PaymentIntent checkouts.
  • data.cart_content.cart_error0 when the cart is healthy. On a cart-level failure it becomes a human-readable message (for example, a purchase option no longer available) and success flips to false.
  • data.delivery_optionsnull unless the cart is a same-day-delivery cart (for_delivery: 1) with items; then it lists courier quotes for checkout.
  • data.delivery_unavailable_reasonnull unless the cart is for delivery and no courier quote could be offered; then it carries a human-readable explanation.
  • data.session.id — The current session ID. It can change between calls, so always send the latest value in the Locally-Api-Session-Id header on your next request. Session IDs eventually expire.
Query Params
qty\[{{ item_id }}\]
array

Quantity of a specific item in the order. The parameter is an array of item IDs and quantities. Example: qty[123]=2,qty[456]=3

qty\[{{ item_id }}\]
int32

Item ID to remove.

string

The domain from which the request is being made.

Headers
string
required

Locally API token must be passed in the header to authenticate the API consumer

string
required

Session ID must be passed in the header to persist the user session. Can expire.

string

JSON Web Token passed in the header to identify the user. Does not expire.

Responses
200

Successful

400

Bad Request

401

Unauthorized

402

Request Failed

403

Forbidden

404

Not Found

429

Too Many Requests

500

Server Error

Language
LoadingLoading…
Response
Click Try It! to start a request and see the response here!