Managing exchanges with the GraphQL Admin API
An exchange represents the intent of a buyer to swap one or more items from an order for different items from the same merchant or a third-party fulfillment location. Merchants can manage their exchanges in Shopify, and exchanges apps can take actions on behalf of merchants.
This guide shows you how to manage exchanges using the GraphQL Admin API.
Anchor to RequirementsRequirements
- Your app can make authenticated requests to the GraphQL Admin API.
- Your app has the
read_returns
andwrite_returns
access scopes. Learn how to configure your access scopes using Shopify CLI. - Your store has existing orders that have been fulfilled. You can return only items that have been fulfilled. If you need to make changes to an unfulfilled item, then you can edit an order.
- You're using API version
2024-07
or higher.
- You've met Shopify's protected customer data requirements.
Anchor to Step 1: Query returnable fulfillmentsStep 1: Query returnable fulfillments
Exchanges are applied to a returnable fulfillment. A returnable fulfillment is an order that has been delivered and is eligible to be returned to the merchant or third-party fulfillment service.
To retrieve the fulfillment line items that can be returned in an order, provide the ID of the order in the returnableFulfillments
query. The response returns the fulfillment line item ID, which you'll use as input to create a return.
You can retrieve the ID of an order using the orders
query.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL query
JSON response
Anchor to Step 2 (Optional): Calculate return financials with exchangesStep 2 (Optional): Calculate return financials with exchanges
You can use the suggestedFinancialOutcome
field to calculate recommended financials for a return with exchanges. This query provides a comprehensive suggestion for refunds, exchanges, and fees, which you can use as input to the returnProcess
mutation.
Example:
For more details, see Migrate to return processing.
Anchor to Step 3: Create a return with exchangesStep 3: Create a return with exchanges
Use the returnCreate
mutation to create a return with exchange line items. This step records the merchant's intent to process a return and/or exchange, but does not confirm the exchange or create fulfillment orders.
You must process the return using the returnProcess
mutation to confirm the exchange and create fulfillment orders. See the next step.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Anchor to Step 4: Process the return to confirm exchangesStep 4: Process the return to confirm exchanges
After creating the return, call the returnProcess
mutation. This step:
- Confirms the return and exchange items.
- Creates fulfillment orders for the exchange items.
- Records the return and exchanges in merchant financial reports.
Example:
- Use the output from
suggestedFinancialOutcome
to help populate the input for this mutation. - Only after this step are fulfillment orders for exchanges created and merchant financials updated.
For more details and advanced scenarios, see Migrate to return processing.
Anchor to Step 5: Collect payment for the exchangeStep 5: Collect payment for the exchange
If a balance is due on the exchange, use the orderInvoiceSend
mutation to send an invoice to the customer before releasing the hold on the exchange.
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 your exchange does not require additional payment from the buyer, you can skip the steps related to fulfillment holds and proceed directly to fulfillment.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Anchor to Step 6: Query for the ID of the fulfillment order on holdStep 6: Query for the ID of the fulfillment order on hold
This step is only required if your exchange fulfillment order is on hold due to a net payable balance.
To fulfill the item for the exchange, you need to release the hold on the fulfillment order by querying for the ID of the fulfillment order that contains the hold.
To retrieve the fulfillment order ID, provide the ID of the order in the order
query. The response returns the fulfillmentOrders
which you can filter to locate the fulfillment order with a status
of ON_HOLD
and a fulfillmentHold
with a reason
of AWAITING_PAYMENT
. You'll use the ID of that fulfillmentOrder
to release the hold in the next step.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL query
JSON response
Anchor to Step 7: Release the hold in order to fulfill the itemStep 7: Release the hold in order to fulfill the item
This step is only required if your exchange fulfillment order is on hold.
After a payment has been received, you can use the fulfillmentOrderReleaseHold
mutation to release the item for the exchange so that it can be fulfilled.
POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
GraphQL mutation
JSON response
Step 8: Fulfill the item
After the hold has been released (if applicable), or immediately after processing for even or refundable exchanges, you can fulfill the item using the fulfillmentOrderSubmitFulfillmentRequest
or fulfillmentCreateV2
mutation mutation.
For most exchanges (even or refundable), you can fulfill the item immediately after processing the return, without any need to check or release a fulfillment hold.
Anchor to Next stepsNext steps
- Learn how to preview and refund duties with the GraphQL Admin API.
- Learn how to manage reverse fulfillment orders with the GraphQL Admin API.
- Learn how to manage reverse deliveries with the GraphQL Admin API.
Anchor to Legacy Exchange Workflow (Deprecated)Legacy Exchange Workflow (Deprecated)
The following workflow applies to API versions prior to 2025-07, or if you have not yet migrated to the new return processing flow. Legacy behavior is still supported for a limited time, but will be removed in a future API version. All new integrations should use the Return Processing workflow.
In earlier API versions, creating a return with exchange line items using returnCreate
would immediately confirm the exchange and create fulfillment orders (all placed on hold). No further processing step was required.
This behavior is deprecated and will be removed in a future API version. For migration steps, see Migrate to return processing.
Step | Before (Legacy) | After (Return Processing) |
---|---|---|
Create return with exchanges | returnCreate | returnCreate |
Confirm exchanges, create fulfillment orders, update financials | (implicit in returnCreate ) | Explicit call to returnProcess required |
Calculate financials | suggestedRefund | suggestedFinancialOutcome |
Hold logic for exchange fulfillment orders | All exchanges on hold | Only net payable exchanges on hold |