Add Item

addItem is used to add to an item to your cart order. Note that cart and order tend to be used interchangeably depending on if you’re looking at it from a developer perspective or a buyer perspective. order is actually an object on the cart resource. For consistency in documentation, it will be referred to as an order for the most part.

Usage

addItem takes in the following object:

interface AddItemRequest {
    lineItem: AddLineItem;
    fulfillment: CartFulfillment;
    locationId: string;
    orderId?: string;
}
  • lineItem represents the item that you want to add to the order. If you use the SDK item helpers, validateItem will provide the starting basis for the AddLineItem object which is shown below.
      interface AddLineItem {
          itemId: string;
          variationId: string;
          quantity?: number;
          modifiers?: AddItemModifier[];
          priceOverride?: {
              amount: number;
              currency: CurrencyTypeEnum;
          };
      }
    
    • itemId is the id on your item resource.
    • variationId is the id of one of the variations on the item (e.g. one of the variations in the item.variations array).
    • quantity is the quantity of the item you want to add to the order. If excluded, defaults to 1.
    • modifiers is an array of modifier selections which is covered in the SDK’s item helpers’ modifier validation.
    • priceOverride is only applicable if your item is a donation (item.square_online_type is DONATION) and your selected variation is the custom amount donation (must be toggled on in the Square Online dashboard) which is indicated by the variation from item.variations having a pricing_type of VARIABLE_PRICING.
      • amount is the numeric currency subunits. For example, in USD, $7.25 would be 725.
      • currency is one of the CurrencyTypes listed below.
          CurrencyType = {
              AUD: 'AUD',
              CAD: 'CAD',
              JPY: 'JPY',
              GBP: 'GBP',
              USD: 'USD',
              EUR: 'EUR'
          };
        
  • fulfillment represents how you want the item/order to get to the buyer. Changing the fulfillment on subsequent add item requests will update the fulfillment on an existing order. This means you can’t have mixed fullfillment items in an order. Otherwise when a buyer goes to their cart they may see some items be invalid depending if they have fulfillment restrictions which don’t match the order’s fulfillment. For example, originally having an order with a food item that’s only available for PICKUP, then adding a shirt with SHIPMENT. The order now has a SHIPMENT fulfillment, and going to cart the food item would show as being invalid because it only supports PICKUP. The CartFulfillment object is shown below.
      interface CartFulfillment {
          fulfillmentType: FulfillmentTypeEnum;
          pickupDetails?: {
              scheduleType?: ScheduleTypeEnum;
              curbsidePickupRequested?: boolean;
              curbsidePickupDetails?: {
                  curbsideDetails: string;
              };
              pickupAt?: string;
          },
          deliveryDetails?: {
              scheduleType?: ScheduleTypeEnum;
              noContactDelivery?: boolean;
              note?: string;
              recipient: DeliveryRecipient;
              deliverAt?: string;
          },
          setPastTimeToCurrent?: boolean;
      }
    
    • scheduleType for either pickupDetails or deliveryDetails. Note that adding an item (including buy now) with ASAP will automatically update the cart time to the earliest available time.
        const ScheduleType = {
            ASAP: 'ASAP',
            SCHEDULED: 'SCHEDULED'
        }
      
    • fulfillmentType can be any of the types below.
        const FulfillmentType = {
            SHIPMENT: 'SHIPMENT',
            PICKUP: 'PICKUP',
            DELIVERY: 'DELIVERY',
            MANUAL: 'MANUAL',
        };
      
      • SHIPMENT, PICKUP, and DELIVERY availability are determined by your individual item fulfillment settings.
      • MANUAL must be used if the square_online_type on your item is DONATION, EVENT, OTHER, or SIMPLE_DIGITAL.
    • pickupDetails is only required if your fulfillmentType is PICKUP. If not provided with PICKUP, the SDK will populate it with the defaults listed below.
      • scheduleType can be set to ASAP or SCHEDULED. The SDK will automatically populate it to ASAP if not provided.
      • curbsidePickupRequested should be set to true if the buyer requested curbside pickup. Otherwise defaults to false if not provided.
      • curbsidePickupDetails is required if curbsidePickupRequested is true.
        • curbsideDetails is a message from the buyer on how they wish to have their curbside pickup completed. You can just set this to an empty string if no message is provided.
      • pickupAt reflects the time the order should be picked up at in RFC 3339 format. For scheduleType ASAP this property does not need to be set.
    • deliveryDetails is only required if your fulfillmentType is DELIVERY.
      • scheduleType can be set to ASAP or SCHEDULED. The SDK will automatically populate it to ASAP if not provided.
      • noContactDelivery denotes whether the delivery should done with no contact. The SDK will default to false if not provided.
      • note is the order note information provided to the seller.
      • deliverAt reflects the delivery start window time for the order in RFC 3339 format. For scheduleType ASAP this property does not need to be set.
      • recipient represents the delivery address information
        interface DeliveryRecipient {
            address : {
                /**
                 * e.g. "New York"
                */
                locality: string;
                /**
                 * e.g. "US"
                */
                country: string;
                /**
                 * e.g. "10013"
                */
                postalCode: string;
                /**
                 * e.g. "New York"
                */
                administrativeDistrictLevel1: string;
                /**
                 * e.g. "New York County"
                */
                administrativeDistrictLevel2?: string;
                /**
                 * e.g. "Town of New York"
                */
                administrativeDistrictLevel3?: string;
                /**
                 * e.g. "District 7"
                */
                subLocality?: string;
                /**
                 * e.g. "Neighborhood"
                */
                subLocality2?: string;
                /**
                 * e.g. "Housing colony"
                */
                subLocality3?: string;
                /**
                 * e.g. "100 6th avenue"
                */
                addressLine1: string;
                addressLine2?: string;
                addressLine3?: string;
            }
        }
        
    • setPastTimeToCurrent indicates whether you want to update the fulfillment time to ASAP when the requested fulfillment time is in the past. The default value is true if not provided.
  • locationId is the ID of the location resource that you want the order fulfilled at (e.g. for PICKUP which store location you’d want the buyer to pickup from). For fulfillmentTypes that are either SHIPMENT or MANUAL, you must set the locationId to your shipping location (configured in the Square Online dashboard).
  • orderId is the ID of the order you want to add the item to. Every Cart API function (except buyNowItem) will return the cart (whose id is the orderId) if you choose to do your own custom multiple order management. Otherwise exclude the field, and the SDK will take care of managing the existing order by creating a new order on initial add, and then adding to that existing order thereafter (which is tracked in the com_cart_id cookie). If you wish to explicitly create a new order, pass an empty string.

Examples

// With the most basic request
const addItemRequest = {
    lineItem: {
        itemId: '47HCEE6ZQUFFY3Y7X52CRVCO',
        variationId: '6YOTMYGOFTJR4PTTYRCLE7BH'
    },
    fulfillment: {
        fulfillmentType: 'SHIPMENT',
        setPastTimeToCurrent: true,
    },
    locationId: 'L36RW9ABXQTEE'
}
// With all the different modifiers
const addItemRequest = {
    lineItem: {
        itemId: '47HCEE6ZQUFFY3Y7X52CRVCO',
        variationId: '6YOTMYGOFTJR4PTTYRCLE7BH',
        modifiers: [
            {
                id: '6WVGAE3PKEHRWZHF54KR2PIN',
                type: 'CHOICE',
                choiceSelections: ['E3MWZ3PJ3VZDQWGW4G3KFZGW', 'GKCUYTB7ARN25J7BTRTOSVHO']
            },
            {
                id: '11ede91fbff63a3ab4dbde667deefb9b',
                type: 'TEXT',
                textEntry: 'my t-shirt-text'
            },
            {
                id: '11ee185ca1cd3e98a25c9e3d692ffefb',
                type: 'GIFT_WRAP',
                choiceSelections: ['11ee185ca1cd7daebd029e3d692ffefb']
            },
            {
                id: '11ee185ca17973e490449e3d692ffefb',
                type: 'GIFT_MESSAGE',
                textEntry: 'happy bday'
            }
        ]
    },
    fulfillment: {
        fulfillmentType: 'SHIPMENT',
        setPastTimeToCurrent: true,
    },
    locationId: 'L36RW9ABXQTEE'
};
// With curbside pickup and quantity
const addItemRequest = {
    lineItem: {
        itemId: '47HCEE6ZQUFFY3Y7X52CRVCO',
        variationId: '6YOTMYGOFTJR4PTTYRCLE7BH',
        quantity: 5
    },
    fulfillment: {
        fulfillmentType: 'PICKUP',
        curbsidePickupRequested: true,
        curbsidePickupDetails: {
            curbsideDetails: 'I will be driving a blue SUV.'
        },
        setPastTimeToCurrent: true,
    },
    locationId: 'L36RW9ABXQTEE'
}
// With a custom amount donation
const addItemRequest = {
    lineItem: {
        itemId: '47HCEE6ZQUFFY3Y7X52CRVCO',
        variationId: '6YOTMYGOFTJR4PTTYRCLE7BH',
        priceOverride: {
            amount: 1000, // $10.00
            currency: 'USD'
        }
    },
    fulfillment: {
        fulfillmentType: 'MANUAL',
        setPastTimeToCurrent: true,
    },
    locationId: 'L36RW9ABXQTEE'
}
// Using the 'addItem' function
try {
    const response = await sdk.cart.addItem(addItemRequest);
} catch (error) {
    // Handle errors
}

Return Value

On success the following object is returned.

interface CartResponse {
    data: {
        cart: string;
        cart_data: Cart;
        validation: {
            scheduled?: {
                valid: boolean;
                error?: string;
                next?: ScheduledValidationNext;
            }
        };
        cart_errors: CartError[]
    };
    response: Response;
}

interface CartError {
    translated: string;
    next?: ScheduledValidationNext;
}

Note: ScheduledValidationNext object can be found here

  • data.cart is the orderId of the order the item was added to (equivalent to id on the cart resource). Only in the case of custom order management would you care about this property, as you don’t need to pass the orderId property for Cart API functions if you want to use the existing order (which is the orderId returned here).
  • data.cart_data is the latest cart. This will include the item that was just added, and an updated and validated fulfillment time if applicable. See Cart Resource for details.
  • data.validation is an empty object if the fulfillment is not schedulable (i.e. pickup or delivery), otherwise provides the scheduled validation. We recommend using data.cart_errors over this as validation is deprecated.
  • data.validation.scheduled.valid is whether or not the pickup or delivery schedule update was valid.
  • data.validation.scheduled.error is provided if there’s an error reason why valid is false. Not included for a simple SCHEDULED validation check.
  • data.validation.scheduled.next is the next valid fulfillment time if available.
  • data.cart_errors is an array of errors that are applicable to the cart for this request. We recommend using this over data.validation as validation is deprecated. Can be empty if there are no errors.
  • data.cart_errors.[].translated is a translated string you can use for buyer facing error handling. This is based off the site language set in the Square Online dashboard.
  • data.cart_errors.[].next is the next valid fulfillment time if applicable to the error and available.
  • response is the raw response from the Fetch API used under the hood.

Cart Order Cookies and Multiple Order Management

Note: The large majority of developers will not need to have any knowledge about the cart order cookies. Only applicable if you’re intentionally wanting to handle multiple orders. Otherwise the SDK will handle it all.

When an item is successfully added to an order, the com_cart_id cookie is updated with the orderId of the order the item was added to. The com_cart_token cookie is also updated which is the order represented by a token instead of an ID. This token is used by existing Square Online pages (i.e. without Custom Sites pages). Meaning if you have a mix of both type of pages, you need both cookies in order to have the order properly represented between the two.

The token is also necessary to properly load the existing cart and checkout routes which are not part of Custom Sites and rely on the token. By default those paths will use the token cookie, but you can also manually pass a token in the URL query if you want to load a specific order (e.g. /s/cart?cart=<orderToken> or /s/checkout?cart=<orderToken>).

That means if you want to manage multiple orders, you’d need to track both the order ID and token from the com_cart_id and com_cart_token cookies after adding an item to the order.

Error Handling

As you may have noticed in the last example above, the SDK Cart APIs will throw if any error occurs. The error thrown is in the object format below.

interface CartError extends Error {
    status?: number;
    fields?: string[];
    errors?: CartValidationErrors;
    cart_errors: CartError[];
}
  • message comes from the Error interface and will include the error message itself. This message will always be in en_US and may include a specific issue that went wrong (e.g. 'Unfortunately the item requested only has 5 item(s) left in stock. Please adjust the quantity and try again.').
  • status is populated if an error status was received on the response (e.g. 500).
  • fields is populated if there are any invalid ids passed (e.g. ['invalidId1', 'invalidId2']). This is only set if the message is 'Invalid IDs passed in payload'.
  • errors is populated if there are any properties that fail the initial validation. CartValidationErrors is an object with a key for each failed validation field and a value of an array of validation errors for that respective field.
      interface CartValidationErrors {
          [key: string]: string[];
      }
    

    An example:

      message: 'fulfillment is required (and 1 more error)',
      errors: {
          'fulfillment': [
          	'fulfillment is required'
          ],
          'fulfillment.fulfillmentType': [
          	'fulfillment.fulfillment type is required'
          ]
      }
    
  • cart_errors are the errors you can use for buyer facing error handling. This is the same format described further above, but you would use the translated value for the potential cart errors. Will always be populated for a thrown error.
try {
    const response = await sdk.cart.addItem(addItemRequest);
} catch (error) {
    // Use `cart_errors` to display a buyer facing error message
}