# Refund an order

> Calculate a refund with suggestedRefund, then refund line items, restock them and return the money with refundCreate and an idempotency key.

Page: https://lintelagency.com/resources/graphql/refund-order

## In short

To refund an order, first ask order.suggestedRefund for the amount and the transaction to refund against, then call refundCreate with refundLineItems (with restockType and location) and transactions (parentId, gateway, kind REFUND, amount). From API version 2026-04, refundCreate requires an @idempotent key, so a retried request can’t refund twice.

## Facts

- **API:** Admin GraphQL API
- **Operations:** order.suggestedRefund, refundCreate
- **Access scope:** write_orders
- **Replaces (REST):** POST /admin/api/orders/{id}/refunds/calculate.json and POST /admin/api/orders/{id}/refunds.json
- **API version:** 2026-10
- **Last checked:** 2 November 2026

## How to use it

1. Send CalculateRefund with the line items and quantities to refund. Leave shipping out, or set refundShipping to refund it too.
2. Copy the suggested transaction’s gateway, amount and parent transaction ID into the refund input with kind REFUND.
3. Choose restockType RETURN (with locationId) to put the items back in stock, or NO_RESTOCK.
4. Send RefundItem with a new idempotency key. Reuse the same key if you retry after a timeout.

## Code

### suggested-refund.graphql

```graphql
query CalculateRefund($orderId: ID!, $refundLineItems: [RefundLineItemInput!]) {
  order(id: $orderId) {
    id
    suggestedRefund(refundLineItems: $refundLineItems, refundShipping: false) {
      amountSet {
        shopMoney {
          amount
          currencyCode
        }
      }
      suggestedTransactions {
        gateway
        kind
        amountSet {
          shopMoney {
            amount
          }
        }
        parentTransaction {
          id
        }
      }
    }
  }
}
```

### suggested-refund.variables.json

```json
{
  "orderId": "gid://shopify/Order/1234567890",
  "refundLineItems": [
    {"lineItemId": "gid://shopify/LineItem/1111111111", "quantity": 1}
  ]
}
```

### suggested-refund.response.json

```json
{
  "data": {
    "order": {
      "id": "gid://shopify/Order/1234567890",
      "suggestedRefund": {
        "amountSet": {
          "shopMoney": {
            "amount": "49.00",
            "currencyCode": "EUR"
          }
        },
        "suggestedTransactions": [
          {
            "gateway": "shopify_payments",
            "kind": "SUGGESTED_REFUND",
            "amountSet": {"shopMoney": {"amount": "49.00"}},
            "parentTransaction": {"id": "gid://shopify/OrderTransaction/2222222222"}
          }
        ]
      }
    }
  }
}
```

### refund-create.graphql

```graphql
mutation RefundItem($input: RefundInput!, $idempotencyKey: String!) {
  refundCreate(input: $input) @idempotent(key: $idempotencyKey) {
    refund {
      id
      totalRefundedSet {
        shopMoney {
          amount
          currencyCode
        }
      }
    }
    userErrors {
      field
      message
    }
  }
}
```

### refund-create.variables.json

```json
{
  "idempotencyKey": "3b8f6c1d-9a2e-4c7b-8d5f-1e2a3b4c5d6e",
  "input": {
    "orderId": "gid://shopify/Order/1234567890",
    "note": "Returned: size too small",
    "notify": true,
    "refundLineItems": [
      {
        "lineItemId": "gid://shopify/LineItem/1111111111",
        "quantity": 1,
        "restockType": "RETURN",
        "locationId": "gid://shopify/Location/1234567890"
      }
    ],
    "transactions": [
      {
        "orderId": "gid://shopify/Order/1234567890",
        "parentId": "gid://shopify/OrderTransaction/2222222222",
        "gateway": "shopify_payments",
        "kind": "REFUND",
        "amount": "49.00"
      }
    ]
  }
}
```

### refund-create.response.json

```json
{
  "data": {
    "refundCreate": {
      "refund": {
        "id": "gid://shopify/Refund/1234567890",
        "totalRefundedSet": {
          "shopMoney": {
            "amount": "49.00",
            "currencyCode": "EUR"
          }
        }
      },
      "userErrors": []
    }
  }
}
```

## Limits and edge cases

- An empty transactions list records the refunded items, and restocks them, without sending money back.
- allowOverRefunding, false by default, decides whether the total refunded may exceed the amount paid.
- returnRefund handles the money for a return created with the returns API; refundCreate also lets you set restocking per line.
- Orders older than 60 days need read_all_orders as well.

## Questions

### How do I refund a Shopify order with GraphQL?

Call refundCreate with the order ID, the line items to refund and a REFUND transaction against the original payment, with an @idempotent key.

### How do I calculate the refund amount first?

Query order.suggestedRefund with the same line items. It returns the amount, taxes and the suggested transactions to use.

### Can I refund without restocking?

Yes. Set restockType to NO_RESTOCK on each refund line item.

## Shopify documentation

- [refundCreate](https://shopify.dev/docs/api/admin-graphql/latest/mutations/refundCreate)
- [Order.suggestedRefund](https://shopify.dev/docs/api/admin-graphql/latest/objects/Order)
- [Idempotent requests](https://shopify.dev/docs/api/usage/idempotent-requests)

## Related

- [Edit an order after it was placed](https://lintelagency.com/resources/graphql/order-editing)
- [Fulfill an order with a tracking number](https://lintelagency.com/resources/graphql/fulfillment-with-tracking)

License: MIT. Free to use in your own store and in client work.
