Store Hugs Developers

Carts and checkout

Make and fill a cart, estimate shipping and hand it to the shop's checkout page with a single-use link.

A cart is named by its token. Make one with createCart, keep its cartToken, and reach it again with cart. The CartSession that cart returns sends the token as the X-Cart-Token header for you. Every change answers with the whole cart, with its lines, totals and coupon.

Each write takes options last: idempotencyKey, signal and headers (see retries).

Create a cart

storefront.createCart(options?: RequestOptions): Promise<Cart>

A new empty cart, named by the returned cartToken. Keep the token, in the shopper's session or a cookie, to come back to the cart. Made on a client with a shopper's access token, the cart is theirs and priced for them. Limited like cart writes (30 a minute, 300 an hour per visitor).

Parameters

Parameter Type
options RequestOptions idempotencyKey, signal and headers (see retries).

Returns

The new Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404Not found, or the shop's plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

const cart = await storefront.createCart();
localStorage.setItem('cartToken', cart.cartToken);

Open a cart

storefront.cart(cartToken: string): CartSession

A CartSession for the cart a token names. Its methods below act on that cart, and its token property holds the token.

Parameters

Parameter Type
cartToken string The cart's token.

Returns

A CartSession. No request is made.

Example

const session = storefront.cart(cart.cartToken);

Get the cart

session.get(): Promise<Cart>

The cart as it is now, priced as the shop's own cart page prices it.

Returns

A Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled: this shop takes no orders through a cart.
429Rate limited.

Example

const cart = await session.get();

Add a product

session.addItem(productId: number, quantity?: number, options?: RequestOptions): Promise<Cart>

Adds a product, or more of one already in the cart. No stock is held until the cart is claimed at checkout. Limited like cart writes.

Parameters

Parameter Type
productId number The product's id.
quantity number How many, from 1 to 10000. Default 1.
options RequestOptions idempotencyKey, signal and headers.

Returns

The changed Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422cart_change_refused with the shopper-worded reason (out of stock…), validation errors, or an idempotency refusal.
429Rate limited.

Example

const cart = await session.addItem(12, 2);

Change a line's quantity

session.updateItem(itemId: number, quantity: number, options?: RequestOptions): Promise<Cart>

Sets a line's quantity. A quantity of 0 removes the line. Limited like cart writes.

Parameters

Parameter Type
itemId number The cart line's id (items[].id).
quantity number The new quantity, from 0 to 10000.
options RequestOptions idempotencyKey, signal and headers.

Returns

The changed Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422cart_change_refused with the shopper-worded reason (out of stock…), validation errors, or an idempotency refusal.
429Rate limited.

Example

const updated = await session.updateItem(cart.items[0].id, 3);

Remove a line

session.removeItem(itemId: number, options?: RequestOptions): Promise<Cart>

Removes a line from the cart.

Parameters

Parameter Type
itemId number The cart line's id (items[].id).
options RequestOptions idempotencyKey, signal and headers.

Returns

The changed Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422cart_change_refused with the shopper-worded reason (out of stock…), validation errors, or an idempotency refusal.
429Rate limited.

Example

const updated = await session.removeItem(cart.items[0].id);

Apply a coupon

session.applyCoupon(code: string, options?: RequestOptions): Promise<Cart>

Checked as the shop's own cart page checks it. A coupon only a known customer can use (first order, per customer) stays on the cart for checkout to decide. Limited to 10 attempts a minute and 60 an hour per visitor.

Parameters

Parameter Type
code string The coupon code, up to 50 characters, any case.
options RequestOptions idempotencyKey, signal and headers.

Returns

The changed Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422The code is unknown or can't be used (errors.code), or an idempotency refusal.
429Rate limited.

Example

const cart = await session.applyCoupon('WELCOME10');

Remove the coupon

session.removeCoupon(options?: RequestOptions): Promise<Cart>

Removes the cart's coupon. Removing an auto-applied coupon stops coupons auto-applying to this cart.

Parameters

Parameter Type
options RequestOptions idempotencyKey, signal and headers.

Returns

The changed Cart:

FieldTypeDescription
cartTokenstringSend it as X-Cart-Token.
modestringenquiry: a wholesale member's cart, sent to the shop as a quotation request. One of checkout, enquiry.
customerIdinteger or nullThe shopper the cart belongs to; null for a guest cart.
itemsarray of CartItem
items[].idinteger
items[].productIdinteger
items[].slugstring or null
items[].titlestring or null
items[].imagestring (uri) or null
items[].quantityinteger
items[].unitPriceMoneyFields: amount, currency, formatted.
items[].lineTotalMoneyFields: amount, currency, formatted.
totalQuantityinteger
subtotalMoneyFields: amount, currency, formatted.
discountMoneyFields: amount, currency, formatted.
couponobject or null
coupon.codestring
coupon.autoAppliedboolean
couponErrorstring or nullWhy the coupon on the cart doesn't apply now.
offersarray of stringLabels of the offers applied.
taxAddedMoneyFields: amount, currency, formatted.
taxIncludedMoneyFields: amount, currency, formatted.
totalBeforeShippingMoneyFields: amount, currency, formatted.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422cart_change_refused with the shopper-worded reason (out of stock…), validation errors, or an idempotency refusal.
429Rate limited.

Estimate shipping

session.estimateShipping(destination: ShippingDestination, options?: RequestOptions): Promise<ShippingEstimate>

The shipping rules the shopper could choose at checkout, priced for a destination as checkout prices them. Only when the shop turned its shipping calculator on (shippingEstimates from shop()). A shop without zones ships anywhere, free. Limited to 30 a minute and 300 an hour per visitor.

Parameters

Parameter Type
destination ShippingDestination The destination's fields, below.
options RequestOptions idempotencyKey, signal and headers.

Request fields

FieldTypeDescription
shippingCountryCode requiredstringISO 3166-1 alpha-3. At most 3 characters.
shippingCitystring or nullAt most 100 characters.
shippingStatestring or nullAt most 255 characters.
shippingPostalCodestring or nullAt most 50 characters.
shippingAddressLine1string or nullAt most 1000 characters.
shippingStateIdinteger or null
shippingCityIdinteger or null
shippingNeighbourhoodIdinteger or null
shippingLocationUnlistedboolean or null

Returns

A ShippingEstimate:

FieldTypeDescription
shipsTobooleanWhether the shop ships to the country.
shipsFreebooleanTrue for a shop without shipping zones (ships anywhere, free).
quotesarray of objectEmpty for an empty or digital-only cart.
quotes[].methodIdinteger
quotes[].namestring
quotes[].costnumberA plain amount in the shop's base currency (not a Money object).
quotes[].isLiveRateboolean
quotes[].isCarrierPriceboolean

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404shipping_estimates_off, cart_not_found, or the shop's plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

const estimate = await session.estimateShipping({
    shippingCountryCode: 'SAU',
    shippingCity: 'Riyadh',
});

if (estimate.shipsTo) {
    estimate.quotes.forEach((quote) => console.log(quote.name, quote.cost));
}

Get a checkout link

session.checkout(options?: CheckoutOptions, request?: RequestOptions): Promise<CheckoutLink>

A single-use link to the shop's checkout page with this cart, valid for 30 minutes, for the shopper's browser to open now. Once opened, the cart belongs to that browser and the token no longer reaches it. When requiresSignIn is true, the cart belongs to a shopper, who must be signed in on the shop. A wholesale member's cart (mode enquiry) leads to the shop's cart page, where it is sent as a quotation request. Limited like cart writes.

Parameters

Parameter Type
options CheckoutOptions The checkout's fields, below.
request RequestOptions idempotencyKey, signal and headers.

Request fields

FieldTypeDescription
returnPathstring or nullPath on the shop's site (Settings → Integration API) the receipt's "Continue shopping" links to. Starts with a single /. At most 500 characters.
cartPathstring or nullPath on the shop's site checkout's back link leads to. Starts with a single /. At most 500 characters.
attributionobject or nullThe visit's UTM tags and click ids, recorded when the link is opened.
attribution.utmSourcestring or nullAt most 255 characters.
attribution.utmMediumstring or nullAt most 255 characters.
attribution.utmCampaignstring or nullAt most 255 characters.
attribution.fbclidstring or nullAt most 255 characters.
attribution.gclidstring or nullAt most 255 characters.
attribution.gbraidstring or nullAt most 255 characters.
attribution.wbraidstring or nullAt most 255 characters.
attribution.dclidstring or nullAt most 255 characters.
attribution.msclkidstring or nullAt most 255 characters.
attribution.ttclidstring or nullAt most 255 characters.
attribution.liFatIdstring or nullAt most 255 characters.
attribution.twclidstring or nullAt most 255 characters.

Returns

A CheckoutLink:

FieldTypeDescription
checkoutUrlstring (uri)Open it in the shopper's browser. Single use.
expiresAtstring (date-time)
modestringOne of checkout, enquiry.
requiresSignInbooleanThe browser must be signed in on the checkout host as the cart's owner.

Errors

StatusWhen
401invalid_api_key: no active Storefront key of this shop, or invalid_customer_token: a bearer token not valid for this shop.
402The shop is suspended (message only).
403origin_not_allowed (publishable key from an unlisted site), secret_key_in_browser, or the shop is not live (message only).
404cart_not_found: the token names no open cart of this shop (opened at checkout, checked out, or another's), or the plan has no Integration API.
409cart_disabled, or idempotency_in_progress.
422Invalid paths or attribution, cart_empty, or an idempotency refusal.
429Rate limited.

Example

const { checkoutUrl } = await session.checkout({
    returnPath: '/thanks',
    cartPath: '/cart',
    attribution: { utmSource: 'newsletter', utmCampaign: 'november' },
});

window.location.assign(checkoutUrl);