--- title: Reading exchange data for integrations description: >- Learn how to sync exchange data to external systems, manage fulfillment for exchanged items, and reconcile financial transactions. source_url: html: >- https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/read-exchanges md: >- https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/read-exchanges.md --- # Reading exchange data for integrations Native exchanges allow merchants to swap items on a return directly within Shopify. This guide helps ERPs, Order Management Systems (OMS), and other integrations sync exchange data, manage fulfillments for exchanged items, and reconcile financial transactions. If you're building a return app and you need to *create* or *manage* exchanges on behalf of a merchant, see [Manage exchanges](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps/manage-exchanges) instead. *** ## Overview When a return with an exchange is created and processed: 1. **Exchange Items**: New items are added to the return as `ExchangeLineItem` objects. 2. **Fulfillment**: A new `FulfillmentOrder` is created on the original order for the exchange items. 3. **Financials**: The value of the returned items is applied to the exchange items. If there is a balance due, the fulfillment order might be held until payment is captured. **Note:** Native exchanges do **not** create a separate new order. They're updates to the existing order. To track the full history of changes to an order, including exchanges, use [sales agreements](#understanding-order-evolution-with-sales-agreements). *** ## The exchange data model Exchanges are part of the `Return` object. * **[`Return`](https://shopify.dev/docs/api/admin-graphql/latest/objects/Return)**: The parent object containing both `returnLineItems` (items coming back) and `exchangeLineItems` (items going out). * **[`ExchangeLineItem`](https://shopify.dev/docs/api/admin-graphql/latest/objects/ExchangeLineItem)**: Represents the new item being sent to the customer. * **[`FulfillmentOrder`](https://shopify.dev/docs/api/admin-graphql/latest/objects/FulfillmentOrder)**: The operational record for fulfilling the exchange items. * **[`SalesAgreement`](https://shopify.dev/docs/api/admin-graphql/latest/interfaces/SalesAgreement)**: The financial record for what was sold (the exchange items) and what was returned. *** ## Fetching exchange data To retrieve exchange details, you can query the `Order` object to access its returns and associated exchange line items. ### Querying exchange line items To retrieve exchange details, query the `Return` object directly using its ID. This is the most efficient method when responding to webhooks like `returns/processed`. ## Get exchange line items ## GraphQL query ```graphql query GetReturnWithExchanges($returnId: ID!) { return(id: $returnId) { id order { id } # Items being returned returnLineItems(first: 10) { edges { node { quantity fulfillmentLineItem { lineItem { name } } } } } # New items being exchanged for exchangeLineItems(first: 10) { edges { node { quantity variantId lineItems { name sku } } } } } } ``` ## JSON response ```json { "data": { "return": { "id": "gid://shopify/Return/123", "order": { "id": "gid://shopify/Order/456" }, "returnLineItems": { "edges": [ { "node": { "quantity": 1, "fulfillmentLineItem": { "lineItem": { "name": "Medium Shirt" } } } } ] }, "exchangeLineItems": { "edges": [ { "node": { "quantity": 1, "variantId": "gid://shopify/ProductVariant/789", "lineItems": [ { "name": "Large Shirt", "sku": "SHIRT-L" } ] } } ] } } } } ``` **Tip:** You can also access exchange data via the `Order` object using the `returns` connection. This is useful if you are syncing orders in bulk and need to check for associated returns. ### Understanding order evolution with sales agreements Use the `agreements` connection on the `Order` object to view the history of sales and returns. This allows you to track the evolution of an order, including the original sale, the return, and the exchange, in a unified log. Returns and exchanges only appear in sales agreements after they're processed. Processing is when merchants confirm which items are being returned or exchanged, making it the appropriate point to record the sale. ## Get order agreements ## GraphQL query ```graphql query OrderAgreements($orderId: ID!) { order(id: $orderId) { agreements(first: 10) { edges { node { __typename id happenedAt ... on ReturnAgreement { return { id name } } sales(first: 10) { edges { node { actionType lineType quantity totalAmount { shopMoney { amount currencyCode } } ... on ProductSale { lineItem { id name } } } } } } } } } } ``` *** ## Reconciling financials When managing returns and exchanges, you may want to associate financial transactions (payments and refunds) with the specific return event. This ensures correct accounting and reporting. For even exchanges—where the returned and exchange items have the same total value including taxes—there are no additional transactions. The original payment covers the new items. ### Access transactions on the return object You can access transaction data directly from the `Return` object using the `transactions` connection for most scenarios. This simplifies the process of associating payments and refunds with specific returns, removing the need to deduce relationships based on amounts and timestamps. The `transactions` connection is populated for the following scenarios: * **POS returns and exchanges**: Includes both refunds and captured payments. * **Online returns and exchanges**: Includes refunds only. ## Get return transactions ## GraphQL query ```graphql query ReturnTransactions($returnId: ID!) { return(id: $returnId) { transactions(first: 5) { edges { node { id kind status amountSet { shopMoney { amount currencyCode } } } } } } } ``` **Online exchange payments:** For online exchanges, captured payments are not yet directly associated with the return. To reconcile these, you can fetch all transactions on the `Order` and match them to the `SalesAgreement` based on the amount and creation timestamp. *** ## Handling fulfillment orders When an exchange is processed, Shopify creates a new `FulfillmentOrder` for the exchange items. * The original fulfillment order (for the returned items) will typically be `CLOSED` or updated. * The new fulfillment order for the exchange items will be `OPEN`. **Holds on net payable exchanges:** Only exchanges with a net payable balance due by the buyer are placed on hold. Even or refundable exchanges are not placed on hold and can be fulfilled immediately after processing. If the exchange is `ON_HOLD` with a reason of `AWAITING_PAYMENT`, you must wait for the hold to be released before fulfilling. ### Fetching fulfillment orders Query the `fulfillmentOrders` connection on the `Order` to identify the new fulfillment requirements. Check the `status` and `fulfillmentHolds` fields to determine if the order is ready for fulfillment. ## Get fulfillment orders ## GraphQL query ```graphql query OrderFulfillments($orderId: ID!) { order(id: $orderId) { fulfillmentOrders(first: 10) { edges { node { id status fulfillmentHolds { reason } lineItems(first: 10) { edges { node { lineItem { name sku } } } } } } } } } ``` *** ## Webhooks To stay synchronized with exchange events, you should subscribe to `returns/processed` and `fulfillment_orders/order_routing_complete`. * `returns/processed`: Triggered when a return is processed. If the return includes exchange items, a new fulfillment order is created at this point. Returns can be partially processed. Check the payload to see which items were processed. * `fulfillment_orders/order_routing_complete`: Triggered when the new fulfillment order has been routed to a location and is ready for fulfillment. For a complete list of return-related webhooks, see the [Return apps overview](https://shopify.dev/docs/apps/build/orders-fulfillment/returns-apps#webhooks). ***