# Remove a promo code from a cart Removes the specified promo code from the cart. The associated discount is removed and totals are recalculated. Returns the updated Cart with the promo removed from promo_codes and the discount removed from totals. The code path parameter is case-insensitive -- the server normalizes it before matching. 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: DELETE /carts/{cart_id}/promo-codes/{code} Version: 1.0.0 Security: oauth2 ## Path parameters: - `cart_id` (string, required) Unique identifier for the cart. - `code` (string, required) The promo code to remove (case-insensitive). Example: "SUMMER25" ## 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 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 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"