Can I perform Bulk operation query to Refund Line Items?

I am trying to migrate from Rest API to GQL and I would like to bulk download refunds, refundLineItems and Transactions. If refundlineItems and transactions are not supported within return, what is the suggested way that I get these details?
I would like to perform this extraction via Bulk query as I will automate the program. Also, I would like to extract updates on the refundlineitems and transactions. how can I design?

Hi @Mayumi_C

You can get everything you want (refunds, refund line items, and associated transactions) via the Admin GraphQL API, and you can do it via Bulk Operations. refundLineItems and transactions are both supported in on the Refund object:



So you don’t need any workaround “outside” the refund – you can get everything from OrderrefundsrefundLineItems and transactions. For bulk export you typically start at orders and walk down to refunds , refundLineItems , and transactions .

An example bulk mutation could look something like this:

mutation RunRefundsBulkOperation {
  bulkOperationRunQuery(
    query: """
    query RefundsBulkQuery {
      orders(first: 100, query: \"created_at:>=2024-01-01\") {
        edges {
          node {
            id
            name
            processedAt
            refunds(first: 50) {
              edges {
                node {
                  id
                  createdAt
                  updatedAt
                  totalRefundedSet {
                    shopMoney {
                      amount
                      currencyCode
                    }
                  }
                  refundLineItems(first: 50) {
                    edges {
                      node {
                        id
                        quantity
                        subtotalSet {
                          shopMoney {
                            amount
                            currencyCode
                          }
                        }
                        lineItem {
                          id
                          sku
                        }
                      }
                    }
                  }
                  transactions(first: 50) {
                    edges {
                      node {
                        id
                        kind
                        status
                        amountSet {
                          presentmentMoney {
                            amount
                            currencyCode
                          }
                        }
                        processedAt
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    """
  ) {
    bulkOperation {
      id
      status
      objectCount
    }
    userErrors {
      field
      message
    }
  }
}

If you need near-real-time updates, you typically complement this with webhooks: use orders/updated or refund-related events to trigger a single-order GraphQL order query that includes refunds , refundLineItems , and transactions , while reserving bulk operations for full backfills and periodic reconciliation.

Hello @Liam-Shopify , I get this error “message”: “Invalid bulk query: Field ‘edges’ doesn’t exist on type ‘Refund’” on above query and if I remove edges and nodes from refunds, I get this “message”: “Queries that contain a connection field within a list field are not currently supported.”

Hi again @Mayumi_C

It does look like you’re hitting a limitation of bulk operations, see: Perform bulk operations with the GraphQL Admin API

Restrictions:

  • Maximum of five total connections in the query.
  • Connections must implement the Node interface.
  • The top-level node and nodes fields can’t be used.
  • Maximum of two levels deep for nested connections

On top of that general description, the bulk validator enforces:

  • You can use a connection like orders { edges { node { … }}} at the root
  • You can nest other connections inside that, but you can’t have a connection field under a simple list ([T]) field in some cases. That’s what “connection field within a list field” is about.

In your case:

  • orders is a connection
  • Order.refunds is a list ([Refund!]!)
  • Refund.refundLineItems is a connection
  • Refund.transactions is a connection

So the path looks like:

orders (connection)
  → node.refunds (list)
    → refundLineItems (connection)  ❌
    → transactions (connection)     ❌

This is why fixing refunds to be a list (no edges) gets past the schema error but then the bulk validator rejects refunds { refundLineItems { … } } because it’s a connection (refundLineItems) under a list field (refunds).

It looks like you’ll need to split this into two pieces:

  1. A bulk operation that only pulls order + refund “headers” (no nested connections under refunds) – this satisfies the bulk restrictions.
  2. A second-phase job that:
  • Streams the JSONL file from the bulk operation
  • Extracts Refund.ids
  • Calls the normal refund query to fetch refundLineItems and transactions

Okay, noted. But will not normal query for many refund ids would result in throttling? Is there a plan for a solution where these objects can be downloaded through Bulk queries?