# Refund an order (full or partial) Processes a full or partial refund for an order. The server determines how to distribute the refund across the order's payment methods using a minimize-cash-refund strategy (non-cash tenders are refunded first). Full refund: Set amount to the order's total paid amount. Partial refund: Set amount to the desired refund amount. Item-level refund: Include line_items to record which items are being refunded (informational -- the amount field determines the refund total). The refund amount must not exceed the order's refundable balance (amount_paid - amount_refunded). Multiple partial refunds can be issued until the full amount has been refunded. Endpoint: POST /orders/{order_id}/refunds Version: 1.0.0 Security: oauth2 ## Path parameters: - `order_id` (string, required) Unique identifier for the order. ## 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" ## Request fields (application/json): - `amount` (object, required) Refund amount in cents. For a full refund, set this to the order's total paid amount. For a partial refund, set this to the desired refund amount. - `amount.amount` (integer, required) Monetary value in the smallest currency unit (cents for USD). Example: 1299 = $12.99. Example: 1299 - `amount.currency` (string, required) ISO 4217 currency code. Example: "USD" - `reason` (string, required) Reason for the refund. This is stored for record-keeping and may be visible to the customer. Enum: "CUSTOMER_REQUEST", "ITEM_UNAVAILABLE", "INCORRECT_ORDER", "QUALITY_ISSUE", "DUPLICATE_CHARGE", "OTHER" - `reason_note` (string,null) Free-text note providing additional context for the refund reason. Required when reason is OTHER. - `line_items` (array) Optional item-level refund detail. When provided, specifies which items are being refunded and their quantities. This is informational for record-keeping -- the refund amount is determined by the amount field, not by summing line item prices. - `line_items.order_item_id` (string, required) ID of the order item being refunded. - `line_items.quantity` (integer, required) Number of units being refunded for this item. - `line_items.reason` (string,null) Optional item-specific reason (overrides the top-level reason for this item). ## Response 201 fields (application/json): - `id` (string, required) Unique identifier for the refund. - `order_id` (string, required) The order this refund applies to. - `status` (string, required) Refund processing status. PENDING means the refund has been accepted and is being processed. COMPLETED means all refund allocations have been processed. FAILED means the refund could not be processed. Enum: "PENDING", "COMPLETED", "FAILED" - `amount` (object, required) Total refund amount. - `amount.amount` (integer, required) Monetary value in the smallest currency unit (cents for USD). Example: 1299 = $12.99. Example: 1299 - `amount.currency` (string, required) ISO 4217 currency code. Example: "USD" - `reason` (string, required) Enum: "CUSTOMER_REQUEST", "ITEM_UNAVAILABLE", "INCORRECT_ORDER", "QUALITY_ISSUE", "DUPLICATE_CHARGE", "OTHER" - `reason_note` (string,null) - `refund_allocations` (array) How the refund was distributed across original payments. The server uses a minimize-cash-refund strategy: non-cash tenders (gift cards, loyalty points) are refunded first, then card payments. - `refund_allocations.payment_id` (string, required) The original payment being refunded. - `refund_allocations.payment_method` (string, required) The payment method used. These are the API-facing values; the server maps them to internal payment processing types. - CREDIT_CARD: Visa, Mastercard, Amex, Discover credit cards - DEBIT_CARD: Debit cards with PIN or signature - CASH: Customer pays cash at the pickup counter. Only meaningful for PICKUP and DINE_IN handoff modes. The order is submitted online but payment is collected in-store. - GIFT_CARD: Store gift cards or third-party gift cards - LOYALTY_POINTS: Loyalty program points redeemed as payment - DIGITAL_WALLET: Apple Pay, Google Pay, or other digital wallets - EBT: SNAP/EBT card. Item eligibility applies -- only SNAP-eligible items (generally food items, excluding hot prepared foods and tobacco) can be paid with EBT. Check allowed_tenders on each menu item. Tolerant Reader: New payment method values may be added in future API versions. Your integration should handle unknown enum values gracefully (e.g., log a warning and skip) rather than failing. Enum: "CREDIT_CARD", "DEBIT_CARD", "CASH", "GIFT_CARD", "LOYALTY_POINTS", "DIGITAL_WALLET", "EBT" - `refund_allocations.amount` (object, required) Amount refunded to this payment method. - `line_items` (array) Item-level refund details, if provided in the request. - `line_items.order_item_id` (string, required) ID of the order item being refunded. - `line_items.quantity` (integer, required) Number of units being refunded for this item. - `line_items.reason` (string,null) Optional item-specific reason (overrides the top-level reason for this item). - `created_at` (string, required) When the refund was created. ## 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"