# Set or update the cart's handoff mode Sets how the customer wants to receive their order. The handoff mode is stored on the cart and used at checkout. Can be called multiple times to change the mode before checkout (e.g., customer switches from PICKUP to DELIVERY). The response returns the updated cart with the stored handoff mode. Idempotency: This endpoint supports idempotent requests. Include an Idempotency-Key header (UUID v4) to safely retry requests. Successful responses are cached for 24 hours; error responses are not cached. Endpoint: PUT /carts/{cart_id}/handoff Version: 1.0.0 Security: oauth2 ## Path parameters: - `cart_id` (string, required) Unique identifier for the cart. ## Header parameters: - `Idempotency-Key` (string, required) A unique key (UUID v4) to ensure idempotent request processing. Required on all POST, PUT, and DELETE requests. If a request is retried with the same key within 24 hours, the server returns the cached success response without re-processing. Error responses are NOT cached -- retrying after an error with the same key will re-execute the request. Generate a new UUID v4 for each unique operation. Reuse the same key only when retrying a failed or timed-out request. Example: "d7a8fbb3-07d4-4e3c-b5f2-9a6c8b1e0f23" ## Response 200 fields (application/json): - `id` (string, required) Unique identifier for the cart. - `location_id` (string, required) The location this cart belongs to. - `customer_id` (string,null) Partner-provided customer identifier. When set, the server applies member-specific pricing during price calculation. Can be set at creation (POST /carts) or updated later (PATCH /carts/{cart_id}). Set to null to revert to anonymous pricing. After changing customer_id, re-calculate prices -- previous pricing may be stale. Example: "CUST-12345" - `status` (string, required) Current cart status. ACTIVE carts accept modifications. CHECKED_OUT carts have been converted to orders via checkout. ABANDONED carts were explicitly deleted by the client. Enum: "ACTIVE", "CHECKED_OUT", "ABANDONED" - `items` (array, required) Line items in the cart. - `items.id` (string, required) Unique identifier for this cart item (generated server-side). - `items.menu_item_id` (string, required) Reference to the menu item (from GET /locations/{location_id}/menu). - `items.name` (string, required) Display name of the menu item (copied from menu at add time). - `items.quantity` (integer, required) Number of this item in the cart. - `items.base_price` (object, required) Base price per unit (from the menu item). - `items.base_price.amount` (integer, required) Monetary value in the smallest currency unit (cents for USD). Example: 1299 = $12.99. Example: 1299 - `items.base_price.currency` (string, required) ISO 4217 currency code. Example: "USD" - `items.modifier_total` (object, required) Total price of all selected modifiers per unit. - `items.item_total` (object, required) Total for this line item: (base_price + modifier_total) * quantity. - `items.modifier_selections` (array, required) Modifiers selected for this item. - `items.modifier_selections.modifier_group_id` (string, required) ID of the modifier group this selection belongs to. - `items.modifier_selections.modifier_id` (string, required) ID of the selected modifier within the group. - `items.modifier_selections.quantity` (integer) Quantity of this modifier. Relevant for modifier groups with allows_duplicates: true (e.g., "Extra Cheese x2"). - `items.modifier_selections.nested_selections` (array) Selections for nested modifier groups. For example, selecting "Steak" as a protein, then choosing "Medium" from the steak preparation sub-group. Supports up to 3 nesting levels, matching the menu's modifier group depth. - `items.special_instructions` (string,null) Customer's special instructions for this item (e.g., "no onions", "extra ice"). Null if none were provided. Max 200 characters. - `items.age_verification_required` (boolean) True if this specific item requires age verification. Copied from the menu item's age_verification_required flag. - `items.minimum_age` (integer,null) Minimum age required to purchase this item (e.g., 21 for tobacco/alcohol). Null if age verification is not required. - `handoff_mode` (any) The handoff mode set for this cart, or null if not yet selected. Set via PUT /carts/{cart_id}/handoff. Required before checkout. - `age_verification_required` (boolean) True if any item in the cart requires age verification (e.g., tobacco, alcohol). This is an informational flag -- age-restricted items are NOT blocked from the cart. The consumer will be verified offline at pickup or delivery. - `promo_codes` (array) Promo codes currently applied to this cart. Only one promo code can be active at a time. Applied via POST /carts/{cart_id}/promo-codes. - `promo_codes.code` (string, required) The promo code string, normalized to uppercase. Codes are case-insensitive on input ("summer25" and "SUMMER25" are treated identically) but always returned as uppercase in responses. Example: "SUMMER25" - `promo_codes.status` (string, required) Current status of this promo code on the cart. - ACTIVE: The code is applied and its discount is reflected in totals. - EXPIRED: The code expired after being applied (e.g., time-limited promo). - REDEEMED: The code was already used (single-use codes) and locked at checkout. Enum: "ACTIVE", "EXPIRED", "REDEEMED" - `promo_codes.discount_preview` (object) Estimated discount this promo code provides. Present when the code is ACTIVE. The actual discount amount appears in the PriceCalculation discounts array with source: PROMO_CODE. - `promo_codes.discount_preview.estimated_discount` (object) Estimated discount amount in cents. - `promo_codes.discount_preview.description` (string) Human-readable description of the discount. Example: "25% off your order (up to $10)" - `promo_codes.applied_at` (string, required) When this promo code was applied to the cart. - `subtotal` (object, required) Sum of all item totals before tax and discounts. - `total_tax` (object, required) Total tax amount for the cart. - `total_discount` (object) Total of cart-level discounts applied to the cart. Item-level discounts are reflected in each item's total. - `fees` (array) Fees currently applied to this cart. Recalculated on each cart modification. Call POST /carts/{cart_id}/calculate for the authoritative fee breakdown. - `fees.id` (string, required) Unique identifier for this fee. Server-generated opaque string used for reconciliation and tracking. - `fees.name` (string, required) Display name of the fee (e.g., "Delivery Fee", "Service Fee", "Bag Fee"). Use this for detailed receipt views. - `fees.fee_type` (string, required) Category of the fee. - DELIVERY: Fee for delivering the order to the customer. - SERVICE: Platform or convenience service fee. - BAG: Per-bag charge required by local regulations. - SMALL_ORDER: Surcharge applied when the cart subtotal is below the location's minimum order amount. The fee covers the shortfall. - OTHER: Fees that do not fit the above categories. Enum: "DELIVERY", "SERVICE", "BAG", "SMALL_ORDER", "OTHER" - `fees.label` (string, required) Short display label for UI rendering (e.g., "Delivery", "Service", "Bag fee"). Use this for compact summary views. - `fees.type` (string) How the fee amount was calculated. - FLAT: A fixed amount regardless of cart contents. - PERCENTAGE: Calculated as a percentage of the subtotal. Enum: "FLAT", "PERCENTAGE" - `fees.value` (string,null) For PERCENTAGE fees, the percentage as a decimal string (e.g., "5.00" for 5%). Null for FLAT fees. - `fees.amount` (object, required) The calculated fee amount in cents (always positive). For PERCENTAGE fees, this is the result of applying the percentage to the subtotal. - `fees.taxable` (boolean, required) Whether tax applies to this fee. The server decides per fee based on local tax rules. When true, this fee's amount is included in the taxable_amount on the PriceCalculation response. - `total_fees` (object) Sum of all fee amounts currently applied to the cart. - `total` (object, required) Grand total: subtotal + total_tax + total_fees - total_discount. - `created_at` (string, required) Timestamp when the cart was created. - `updated_at` (string, required) Timestamp when the cart was last modified. ## Response 400 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED" ## Response 401 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED" ## Response 404 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED" ## Response 409 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED" ## Response 422 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED" ## Response 429 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED" ## Response 500 fields (application/json): - `error` (object, required) - `error.code` (string, required) Machine-readable error category. Use this field for programmatic error handling (e.g., retry on RATE_LIMIT_ERROR, re-authenticate on AUTHENTICATION_ERROR). Enum: "AUTHENTICATION_ERROR", "INVALID_REQUEST_ERROR", "RATE_LIMIT_ERROR", "NOT_FOUND_ERROR", "CONFLICT_ERROR", "INTERNAL_ERROR" - `error.message` (string, required) Human-readable error description. Safe to display to developers in logs or debugging tools. Do not display to end users. - `error.detail` (string) Additional context about the error, including suggestions for resolution. May include specific field values or limits that were exceeded. - `error.request_id` (string, required) Unique identifier for this request. Include this value when contacting Tote Developer Support for troubleshooting. - `error.field` (string,null) JSON pointer to the field that caused the error. Null if the error is not field-specific. Example: "items[0].modifier_groups[1].modifiers" - `error.change_reasons` (array) Machine-readable reasons why the resource state changed, causing the conflict. Present on checkout 409 responses when expected_total does not match the current total. Clients should re-fetch the cart and call POST /carts/{cart_id}/calculate to get the updated total before retrying checkout. Enum: "PROMO_EXPIRED", "DISCOUNT_CHANGED", "ITEM_PRICE_CHANGED", "ITEM_UNAVAILABLE", "FEE_CHANGED"