--- title: Migrate to return processing description: Learn how to migrate your app to be compatible with return processing. source_url: html: https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing md: https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing.md --- ExpandOn this page * [What is changing?](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#what-is-changing) * [Who needs to take action?](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#who-needs-to-take-action) * [Key changes with return processing](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#key-changes-with-return-processing) * [Migration steps](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#migration-steps) * [Step 1: Update APIs for refunds](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-1-update-apis-for-refunds) * [Step 2: Adapt your return workflow for exchanges](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-2-adapt-your-return-workflow-for-exchanges) * [Step 3: Update webhook handlers](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-3-update-webhook-handlers) * [Step 4: Test your integration](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-4-test-your-integration) * [Timeline](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#timeline) * [Next steps](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#next-steps) * [Migration Checklist](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#migration-checklist) # Migrate to return processing In API version 2025-07, Shopify introduced [`returnProcess`](https://shopify.dev/docs/api/admin-graphql/unstable/mutations/returnProcess) to enhance the lifecycle management of returns. Processing a return means confirming the return items, exchange items, and return fees on the return, thereby updating a merchant's financial reports. This step will also result in exchange items being confirmed (if applicable). This document outlines these updates in detail and offers migration best practices. *** ## What is changing? 1. **Merchant reporting** - Previously, a merchant's financial report would include a return when the return was created or approved. Moving forward, a return will only be recorded as a [`Sale`](https://shopify.dev/docs/api/admin-graphql/latest/interfaces/Sale) when it has been processed. 2. **Confirming exchange items** - Previously, creating or approving a return would immediately confirm an [`exchangeLineItem`](https://shopify.dev/docs/api/admin-graphql/latest/objects/ExchangeLineItem) on the return and create a [`FulfillmentOrder`](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder). This will now only happen when the exchange line item has been processed. 3. **Holding exchange fulfillment orders** - Previously, all fulfillment orders created for an exchange would automatically be placed on hold. Moving forward only exchanges with a balance owed by the buyer will be automatically placed on hold. An even or refundable exchange will not be placed on hold. **Note:** In addition to new mutations, the way you obtain suggested refund and financial outcomes has changed. See [Migrating from `suggestedRefund` to `suggestedFinancialOutcome`](#migrating-from-suggestedrefund-to-suggestedfinancialoutcome) for details on updating your integration. *** ## Who needs to take action? 1. Partners that create returns with an [`exchangeLineItem`](https://shopify.dev/docs/api/admin-graphql/latest/objects/ExchangeLineItem) 2. Partners that create returns with a [`ReturnShippingFee`](https://shopify.dev/docs/api/admin-graphql/latest/objects/ReturnShippingFee) or [`RestockingFee`](https://shopify.dev/docs/api/admin-graphql/latest/objects/RestockingFee) 3. Partners that assume a merchant's financial report will include returns when the return is created Although issuing refunds to the original payment method **on a return** will continue to work with [`returnRefund`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/returnRefund) or [`refundCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/refundCreate), returnRefund will be a legacy API, and using refundCreate for returns causes undesired effects for certain cases (example: risk of refunding the wrong item when there are multiple quantities of the same item on an order). The best practice is to integrate with `returnProcess` for this use case as well. *** ## Key changes with return processing The following table outlines the key differences introduced with return processing: | Action | Before return processing | After return processing | | - | - | - | | Return items are recorded as a Sale | `returnCreate` or `returnApproveRequest` | `returnProcess` or `returnRefund` or `refundCreate` | | Exchange items are confirmed and fulfillment orders are created | `returnCreate` or `returnApproveRequest` | `returnProcess` | | Return fees are recorded as a Sale | `returnCreate` or `returnApproveRequest` | `returnProcess` | *** ## Migration steps Follow these steps to migrate your app from the legacy returns API to the return processing API: 1. **Update APIs for refunds on returns with and without return fees**: Replace calls to the legacy refund mutations with the return processing mutation. 2. **Adapt your return workflow for exchanges**: Call the return processing mutations on returns with exchange line items. 3. **Update webhook handlers**: Subscribe to the new return/process webhooks (if applicable). 4. **Test your integration**: Ensure your app works correctly with the new API. *** ## Step 1: Update APIs for refunds ### Migrating from the legacy `returnRefund` mutation to the new `returnProcess` mutation **Before: Using returnRefund** ```graphql mutation ReturnRefund { returnRefund( returnRefundInput: { # The ID of the return to refund returnId: "gid://shopify/Return/3769532472", # Return line items to refund returnRefundLineItems: [ { returnLineItemId: "gid://shopify/ReturnLineItem/5392564280", quantity: 1 } ], # Refund shipping costs refundShipping: { shippingRefundAmount: { amount: 20.00, currencyCode: USD } }, # Payment transaction information from the suggestedTransactions orderTransactions: [ { # Parent transaction ID parentId: "gid://shopify/OrderTransaction/15011711647800", # Amount to refund transactionAmount: { amount: 124.64, currencyCode: USD } } ], # Optional: Notify the customer about the refund notifyCustomer: true } ) { refund { id createdAt note totalRefundedSet { shopMoney { amount currencyCode } presentmentMoney { amount currencyCode } } # Return associated with this refund return { id status } } userErrors { field message code } } } ``` **After: Using returnProcess** ```graphql mutation ReturnProcess { returnProcess( input: { # The ID of the return to process returnId: "gid://shopify/Return/3774119992", # Return line items with disposition decisions returnLineItems: [ { id: "gid://shopify/ReturnLineItem/5398200376", quantity: 1, dispositions: [ { reverseFulfillmentOrderLineItemId: "gid://shopify/ReverseFulfillmentOrderLineItem/3367010360", quantity: 1, locationId: "gid://shopify/Location/67829006392", # Required for RESTOCKED dispositionType: RESTOCKED } ] } ], # Financial transfer information (refunds) financialTransfer: { issueRefund: { orderTransactions: [ { # Parent transaction ID from the response parentId: "gid://shopify/OrderTransaction/15012547592248", # Amount to refund from the response transactionAmount: { amount: 329.25, currencyCode: USD } } ] } }, # Optional: Notify the customer about the refund notifyCustomer: true } ) { return { id status refunds(first: 10) { edges { node { id createdAt totalRefundedSet { shopMoney { amount currencyCode } presentmentMoney { amount currencyCode } } } } } } # Any user-level errors userErrors { field message code } } } ``` **Key differences between returnRefund and returnProcess** 1. **Combined process**: `returnProcess` handles both disposition decisions (restock/not restock) and financial processing in a single call, while `returnRefund` only handled the financial aspect. 2. **Structure changes**: Financial information is now under the `financialTransfer` object instead of being directly at the root level of the input. **Tip:** When preparing inputs for the new `returnProcess` mutation, use the `suggestedFinancialOutcome` field on the `return` object to generate recommended values for refunds, exchanges, and fees. This replaces the legacy `suggestedRefund` field. ### Migrating from the `refundCreate` mutation to the new `returnProcess` mutation **Before: Using refundCreate** ```graphql mutation CreateRefund { refundCreate( input: { # The ID of the order to refund orderId: "gid://shopify/Order/13788583067704" # Optional: Add a note about why the refund is being issued note: "Full refund for order #1856" # Optional: Whether to notify the customer about the refund notify: true # Line items to refund with restock information refundLineItems: [ { lineItemId: "gid://shopify/LineItem/39756510527544", quantity: 1, restockType: RETURN, locationId: "gid://shopify/Location/67829006392" }, { lineItemId: "gid://shopify/LineItem/39756510560312", quantity: 1, restockType: RETURN, locationId: "gid://shopify/Location/67829006392" } ], # Transaction details for the refund transactions: [ { amount: "1426.75", gateway: "manual", kind: REFUND, orderId: "gid://shopify/Order/13788583067704", parentId: "gid://shopify/OrderTransaction/15012617093176" } ] } ) { refund { id note totalRefundedSet { shopMoney { amount currencyCode } } } userErrors { field message } } } ``` **After: Using returnProcess** ```graphql mutation ProcessReturn { returnProcess( input: { # The ID of the return to process returnId: "gid://shopify/Return/3774119992", # Return line items with disposition decisions returnLineItems: [ { id: "gid://shopify/ReturnLineItem/5398200376", quantity: 1, dispositions: [ { reverseFulfillmentOrderLineItemId: "gid://shopify/ReverseFulfillmentOrderLineItem/3367010360", quantity: 1, locationId: "gid://shopify/Location/67829006392", dispositionType: RESTOCKED } ] }, { id: "gid://shopify/ReturnLineItem/5398200377", quantity: 1, dispositions: [ { reverseFulfillmentOrderLineItemId: "gid://shopify/ReverseFulfillmentOrderLineItem/3367010361", quantity: 1, locationId: "gid://shopify/Location/67829006392", dispositionType: RESTOCKED } ] } ], # Financial transfer information (refunds) financialTransfer: { issueRefund: { orderTransactions: [ { parentId: "gid://shopify/OrderTransaction/15012617093176", transactionAmount: { amount: "1426.75", currencyCode: USD } } ] } }, # Optional: Notify the customer about the refund notifyCustomer: true } ) { return { id status refunds(first: 5) { edges { node { id totalRefundedSet { shopMoney { amount currencyCode } } } } } } userErrors { field message } } } ``` **Key differences between refundCreate and returnProcess** 1. **Return-based vs Order-based**: `returnProcess` works with return objects rather than directly with orders, providing better lifecycle management of returns. 2. **Line item precision**: With `refundCreate`, which references order `LineItem`s directly, there's no guarantee that you are refunding the item you intended to refund when multiple quantities of the same product exist on an order. `returnProcess` uses `ReturnLineItem`s that are specifically associated with the items being returned, ensuring the exact returned items are properly processed. 3. **Comprehensive return handling**: `returnProcess` can handle all return types including exchanges, whereas `refundCreate` only works for net refundable returns. This means `returnProcess` provides a complete solution for the entire returns lifecycle, including exchange fulfillment orders. 4. **Return fee support**: `returnProcess` can record return fees (such as restocking or shipping fees) on the sales ledger, providing accurate financial reporting for merchants. `refundCreate` lacks this capability, potentially leading to inconsistencies in financial reporting for return-related fees. ### Migrating from `suggestedRefund` to `suggestedFinancialOutcome` With the introduction of the new return processing API, Shopify has also modernized how apps can obtain suggested financial transactions for a return. Previously, the `suggestedRefund` field on the `return` object provided a recommended refund structure, typically used as input to the legacy `refundCreate` mutation. Now, the `suggestedFinancialOutcome` field provides a more comprehensive and flexible suggestion, designed to be used with the new `returnProcess` mutation. This section explains the differences between these two fields and how to migrate your integration. #### Key Differences | Aspect | `suggestedRefund` (Legacy) | `suggestedFinancialOutcome` (New) | | - | - | - | | **Purpose** | Suggests refund amounts for a return, to be used with `refundCreate` or `returnRefund` | Suggests a complete financial outcome (refunds, exchanges, fees, allocations) for a return, to be used with `returnProcess` | | **Inputs** | - Return refund line items - Shipping refund - Duties - Additional fees - (Optionally) apply deductions | - Return line items - Exchange line items - Shipping refund - Duties - Additional fees - Refund method allocation (e.g., original payment method, store credit) | | **Coverage** | Focused on refunds only | Handles refunds, exchanges, fees, and supports allocation of refund methods | | **Output Structure** | Refund amounts and related fields | Detailed breakdown of all financial components, including refund methods, transactions, deductions, and more | | **Mutation Usage** | `refundCreate` or `returnRefund` | `returnProcess` | | **Extensions** | Limited | Designed for future extensions and more complex return scenarios | #### Example Migration **Before: Using `suggestedRefund`** ```graphql query { return(id: "gid://shopify/Return/123") { suggestedRefund( returnRefundLineItems: [ { returnLineItemId: "gid://shopify/ReturnLineItem/456", quantity: 1 } ], refundShipping: { shippingRefundAmount: { amount: "5.00", currencyCode: USD } }, refundDuties: [ { dutyId: "gid://shopify/Duty/789", refundType: FULL } ], refundAdditionalFees: [ { additionalFeeId: "gid://shopify/AdditionalFee/101" } ] ) { amount { shopMoney { amount currencyCode } } # ...other fields } } } ``` The result would be used as input to the `refundCreate` or `returnRefund` mutation. **After: Using `suggestedFinancialOutcome`** ```graphql query { return(id: "gid://shopify/Return/123") { suggestedFinancialOutcome( returnLineItems: [ { id: "gid://shopify/ReturnLineItem/456", quantity: 1 } ], exchangeLineItems: [ { id: "gid://shopify/ExchangeLineItem/789", quantity: 1 } ], refundShipping: { shippingRefundAmount: { amount: "5.00", currencyCode: USD } }, refundDuties: [ { dutyId: "gid://shopify/Duty/789", refundType: FULL } ], refundAdditionalFees: [ { additionalFeeId: "gid://shopify/AdditionalFee/101" } ], refundMethodAllocation: ORIGINAL_PAYMENT_METHODS ) { totalReturnAmount { shopMoney { amount currencyCode } } financialTransfer { suggestedTransactions { amountSet { shopMoney { amount currencyCode } } # ...other fields } suggestedRefundMethods { amount { shopMoney { amount currencyCode } } # ...other fields } # ...other fields } selectedDeductions { returnShippingFeesSubtotal { shopMoney { amount currencyCode } } restockingFeesSubtotal { shopMoney { amount currencyCode } } # ...other fields } # ...other fields } } } ``` The result is then used as input to the `returnProcess` mutation, which can process refunds, exchanges, and fees in a single call. #### Migration Steps 1. **Update your query:** Replace any usage of `suggestedRefund` with `suggestedFinancialOutcome` in your GraphQL queries. Adjust the input arguments to include both return and exchange line items, as well as any new fields relevant to your workflow (such as `refundMethodAllocation`). 2. **Review the output:** The structure of the response is more detailed. Update your code to extract the relevant suggested transactions, refund methods, and deductions as needed. 3. **Prepare the mutation input:** Use the output from `suggestedFinancialOutcome` to construct the input for the `returnProcess` mutation. You may modify the suggested values as needed to fit your business logic. 4. **Test thoroughly:** Ensure that your integration correctly handles all return scenarios, including refunds, exchanges, and fees. #### Best Practices * **Use suggestions as a starting point:** The values returned by `suggestedFinancialOutcome` are recommendations. You can modify them before passing to `returnProcess` if your workflow requires it. * **Handle errors gracefully:** Both fields may return user errors if the input is invalid (e.g., mismatched currencies, invalid IDs). Ensure your integration checks for and handles these errors. * **Support new features:** The new API supports more complex scenarios, such as allocating refunds to store credit or handling multiple exchange line items. Take advantage of these features to provide a better merchant and buyer experience. *** ## Step 2: Adapt your return workflow for exchanges Another key change with return processing is the workflow for exchanges: **Before**: Partners only needed to call `returnCreate` or `returnAppproveRequest` to create a return with exchange line items. This automatically confirmed exchange items and created fulfillment orders. **Now**: Partners must follow a two-step process: 1. Call `returnCreate` or `returnAppproveRequest` to create the return with exchange line items 2. Call `returnProcess` to confirm the return and exchange line items The `returnProcess` call is now required to: 1. Commit those items to the sales ledger 2. Create fulfillment orders for the exchange items Additionally, whereas previously all fulfillment orders driven by exchanges would be placed on hold, now only fulfillment orders created for exchanges that have a net payable balance due by the buyer will be placed on automatic hold. ### Example: Processing a net even exchange ```graphql mutation ReturnProcess { returnProcess( input: { # The ID of the return to process returnId: "gid://shopify/Return/3774152760", # Return line items with disposition decisions returnLineItems: [ { id: "gid://shopify/ReturnLineItem/5398233144", quantity: 1, dispositions: [ { reverseFulfillmentOrderLineItemId: "gid://shopify/ReverseFulfillmentOrderLineItem/3367043128", quantity: 1, locationId: "gid://shopify/Location/67829006392", # Required for RESTOCKED dispositionType: RESTOCKED } ] } ], # Exchange line items to process exchangeLineItems: [ { id: "gid://shopify/ExchangeLineItem/120586296", quantity: 1 } ], # Optional: Notify the customer about the exchange notifyCustomer: true } ) { return { id status refunds(first: 10) { edges { node { id createdAt totalRefundedSet { shopMoney { amount currencyCode } presentmentMoney { amount currencyCode } } } } } } # Any user-level errors userErrors { field message code } } } ``` In this example, the mutation processes both the return line items (with restock decisions) and the exchange line items. Since this is a net even exchange (no additional payment required from the buyer), the created fulfillment orders will not be placed on hold and can be fulfilled immediately. *** ## Step 3: Update webhook handlers Subscribe to the new `returns/process` webhook. This webhook will be triggered when a return has been fully or partially processed. The return's status is `CLOSED` when all items have been processed and a restock decision has been made. *** ## Step 4: Test your integration Before deploying to production, thoroughly test your updated integration: 1. Create test orders and initiate returns 2. Process returns using the `returnProcess` mutation 3. Verify webhook handling for all return events 4. Confirm that exchanges are properly created and managed 5. Validate that refunds are accurately issued *** ## Timeline Return processing is available starting in API version 2025-07. Existing return apps that use `returnRefund` or `refundCreate` must migrate to `returnProcess` to ensure consistent behavior and avoid disruptions. *** ## Next steps * Review the [`returnProcess` mutation API reference](https://shopify.dev/docs/api/admin-graphql/unstable/mutations/returnProcess) * Learn more about [returns apps](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps) * Understand how to [manage returns](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/build-return-management) with the GraphQL Admin API * Set up [webhook handlers](https://shopify.dev/docs/apps/build/webhooks/subscribe) for return processing events *** ## Migration Checklist * Update all refund and return processing flows to use `returnProcess` instead of `refundCreate`/`returnRefund` * Replace all queries to `suggestedRefund` with `suggestedFinancialOutcome` * Update your code to handle the new output structure from `suggestedFinancialOutcome` * Test all return, refund, and exchange scenarios end-to-end * Update documentation and team knowledge to reflect these changes *** * [What is changing?](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#what-is-changing) * [Who needs to take action?](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#who-needs-to-take-action) * [Key changes with return processing](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#key-changes-with-return-processing) * [Migration steps](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#migration-steps) * [Step 1: Update APIs for refunds](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-1-update-apis-for-refunds) * [Step 2: Adapt your return workflow for exchanges](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-2-adapt-your-return-workflow-for-exchanges) * [Step 3: Update webhook handlers](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-3-update-webhook-handlers) * [Step 4: Test your integration](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#step-4-test-your-integration) * [Timeline](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#timeline) * [Next steps](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#next-steps) * [Migration Checklist](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/migrate-to-return-processing#migration-checklist)