Rest vs GraphQL - how to retrieve discount codes as shopMoney

I would like to see the amount of each discount code in the GraphQL query order results, but I see a mixed payload of amounts and percentages.

In the order update webhook, the payload arrives with discount codes in an array in the desired format:

“discount_codes”: [
   {
      "amount": "10.00",
      "code": "discounttest",
      "type": "fixed_amount"
   },
   {
      "amount": "19.99",
      "code": "foo",
      "type": "percentage"
   }
]

However, when I query the order data via GraphQL, the discountCodes array is just an array of strings and the discountApplications attribute only lists the percentage discount, not the actual value.

{
   "index": 1,
   "allocationMethod": "ACROSS",
   "__typename": "DiscountCodeApplication",
   "value": {
      "percentage": 10.0,
      "__typename": "PricingPercentageValue"
   },
   "targetType": "LINE_ITEM",
   "targetSelection": "ALL",
   "code": "foo"
}

Is there a way to extract the value for each discount in the GraphQL query without calculating it?

If I do end up calculating the discount (not my first choice), I’m also trying to understand the rounding rule Shopify applies to currency. In this example, 10% of the total order amount of 199.98 is 19.998. If I round to the nearest penny, I end up with a discount of 20.00. Shopify uses 19.99 and appears to truncate. What rule is Shopify using here and throughout?

@Tom_Raney I don’t think discountCodes is the field you want for this in GraphQL. In Admin GraphQL, discountCodes is only the list of code strings, and discountApplications describes the discount rule/application, not the final calculated money amount.

The field that carries the actual calculated discount amount is discountAllocations.

Shopify’s GraphQL docs describe it this way: DiscountApplication captures the discount’s intent/rules, while DiscountAllocation represents the actual amount discounted on a line item or shipping line.

So for a webhook-style result like:

{
  "code": "foo",
  "amount": "19.99",
  "type": "percentage"
}

you need to query line item and shipping line discount allocations, then group/sum them by the related discount application.

Example query:

query OrderDiscounts($id: ID!) {
  order(id: $id) {
    id
    name
    discountCodes

    currentTotalDiscountsSet {
      shopMoney {
        amount
        currencyCode
      }
    }

    lineItems(first: 100) {
      nodes {
        id
        name
        discountAllocations {
          allocatedAmountSet {
            shopMoney {
              amount
              currencyCode
            }
          }
          discountApplication {
            index
            targetType
            value {
              __typename
              ... on PricingPercentageValue {
                percentage
              }
              ... on MoneyV2 {
                amount
                currencyCode
              }
            }
            ... on DiscountCodeApplication {
              code
            }
          }
        }
      }
    }

    shippingLines(first: 25) {
      nodes {
        title
        discountAllocations {
          allocatedAmountSet {
            shopMoney {
              amount
              currencyCode
            }
          }
          discountApplication {
            index
            targetType
            value {
              __typename
              ... on PricingPercentageValue {
                percentage
              }
              ... on MoneyV2 {
                amount
                currencyCode
              }
            }
            ... on DiscountCodeApplication {
              code
            }
          }
        }
      }
    }
  }
}

Then sum:

lineItems.nodes[].discountAllocations[].allocatedAmountSet.shopMoney.amount
shippingLines.nodes[].discountAllocations[].allocatedAmountSet.shopMoney.amount

grouped by:

discountApplication.index

or, for code discounts:

discountApplication.code

I tested this against a real order. The REST/webhook-style discount_codes.amount was 30.74, and the GraphQL allocations were:

23.06
 7.68
-----
30.74

So the GraphQL allocation total matched the order’s actual discount amount exactly.

For the rounding question: I would avoid recreating Shopify’s calculation if possible. The allocation fields already contain Shopify’s finalized result after entitlement rules, allocation method, line splitting, quantity handling, shipping/line target, and currency rounding. In the example I tested, the result was consistent with Shopify allocating at a more granular level than simply doing percentage * order subtotal and rounding once at the end.

In short: use discountApplications to identify what discount was applied, but use discountAllocations.allocatedAmountSet to get the actual money amount.

Also note that if an order has more than 100 line items, you’ll need to paginate lineItems.

Thank you for your detailed response. This is great advice.