Close of Day definitions
Version 2026-10-02
Version 2026-10-02, matching DEFINITIONS_VERSION in src/engine.mjs. Admin GraphQL 2026-10; the fields were read on the 2026-07 reference pages and checked against the 2026-10 release notes on 2026-10-02.
This page lists every line Close of Day shows. For each line it gives:
- Shopify's own definition, with the page it came from
- the formula
src/engine.mjsuses - whether the brief's belief was confirmed, corrected, or is Close of Day's own (Shopify says nothing on it)
Anything Shopify's pages do not settle is listed under Unconfirmed at the end. That list is part of the engine's contract: each item is an assumption to check against a real store's Finance summary (ROADMAP D5).
How the quotes were taken: the pages were read through a fetch tool that summarises each page before answering. Text in quotation marks is the wording it returned as verbatim. Twice, two fetches of the same field disagreed, and both versions are given. Where the tool paraphrased instead of quoting, the text is marked "paraphrase".
Help Center pages, short names used below:
- Sales report: https://help.shopify.com/en/manual/reports-and-analytics/shopify-reports/report-types/default-reports/sales-report
- Finances report: https://help.shopify.com/en/manual/reports-and-analytics/shopify-reports/report-types/default-reports/finances-report
- Analytics fields: https://help.shopify.com/en/manual/reports-and-analytics/shopify-reports/report-types/analytics-fields
- Sales discrepancies: https://help.shopify.com/en/manual/reports-and-analytics/discrepancies/sales-discrepancies
- Checkout tips: https://help.shopify.com/en/manual/checkout-settings/tips
- POS tips: https://help.shopify.com/en/manual/sell-in-person/shopify-pos/tips
API reference pages are under https://shopify.dev/docs/api/admin-graphql/2026-07/. They are written below as objects/Order, enums/OrderTransactionKind and so on.
Conventions
Money
- Every amount is
shopMoney.amountin the shop currency. It is parsed into integer minor units and summed as integers, then printed at the currency's precision. - The precision comes from
Intl: 2 for USD, 0 for JPY, 3 for KWD. - An amount with more decimal places than the currency allows is rounded half away from zero, with a warning.
objects/MoneyV2: amount is "A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99."scalars/Decimal: "A signed decimal number, which supports arbitrary precision and is serialized as a string."
Signs. Reductions are negative numbers: discounts, returns, shipping discounts and refunds, reversed tax, refunded payments. So every formula below adds its parts. For example, net sales = gross sales + discounts + returns.
Dating. Each figure is posted to the day of the event that produced it, read in the store's time zone (Shop.ianaTimezone: "The shop's time zone as defined by the IANA."):
| Event | Dated by | Fallback |
|---|---|---|
| Sale | Order.processedAt | createdAt |
| Refund (return, cancellation, refunded shipping, tax, duties, adjustment) | Refund.processedAt | Refund.createdAt |
| Units removed with no refund | Order.cancelledAt | the sale's date |
| Payment | OrderTransaction.processedAt | createdAt |
An order sold before the range still contributes its refunds and payments that fall inside it.
What is counted
- Test orders are left out, both in the search (
test:false) and again in the engine. - Transactions with
test: trueare left out too. - Cancelled orders are counted.
Location filter. With locationId set, each event is kept only if it is attributed to that location:
- a sale or a removal: to
Order.retailLocation - a refund: to the location of the refund's first transaction that has one, else the order's
- a payment: to
OrderTransaction.location, else the order's
Prices that include tax (Order.taxesIncluded):
- Each line's tax (the sum of its tax lines) is taken out of its discounted total to give net.
- Gross is scaled by the same ratio: gross = round(original × net ÷ (original − discount)), and discount = gross − net.
- Refund line and refunded shipping subtotals have their tax taken out the same way.
include-exclude-taxespage: "Setting up your prices to include taxes doesn't affect your tax reporting." It does not say how gross sales is computed (Unconfirmed).
Sales
Gross sales — sales.grossSales
- Shopify, Sales report: "product price x quantity (before taxes, shipping, discounts, and sales reversals)"
- Shopify, Finances report: "product selling price x ordered quantity. Gross sales does not include discounts, sales reversals, taxes, shipping, or fees."
- Close of Day: the sum of
LineItem.originalTotalSetover product lines (not gift card lines, not tip lines), on the sale date.objects/LineItem: "In shop and presentment currencies, the total price of the line item when the order was created. This value doesn't include discounts." The tax is taken out when prices include tax (Conventions). - Brief: "gross sales is price times quantity before taxes, shipping, discounts and returns". Confirmed.
Discounts — sales.discounts
- Shopify, Sales report: "line item discount + order level discount share for a collection of sales"
- Shopify, Finances report: "product discount + the product's proportional share of a cart-wide discount."
- Close of Day:
- −(the sum of
discountAllocations.allocatedAmountSeton product lines), on the sale date. objects/DiscountAllocation: "The actual amount discounted on a line item or shipping line. … The DiscountAllocation object shows the final calculated discount amount applied to each line."- Discounts on shipping lines are not here. They are in Shipping, as the Sales report's Shipping formula has them.
- −(the sum of
- Brief: "discounts are line and order discounts". Confirmed. That
LineItem.discountAllocationscarries the line's share of an order-level discount is Unconfirmed. - Self-check:
normaliseOrderwarns when the allocations do not sum toOrder.totalDiscountsSet, which "includes both order and line level discounts".
Returns — sales.returns (Shopify: Sales reversals)
Shopify, Sales report
- "Returns (Deprecated)": "The value of goods returned by a customer. Returns display as a negative number on the date the return was processed."
- "This term has been deprecated. Refer to Sales reversals for the updated terminology and definition."
- Sales reversals: "All order adjustments that result in negative monetary value. Sales reversals include the value of returned products, as well as order cancellations, edits, adjustments to shipping, taxes, fees, and discounts."
- Dating: "Sales display in your sales reports as a positive value for the day that they were made, and reversals display as a negative value for the day that they were processed."
Shopify, Finances report. Sales reversals: "The value of goods returned by a customer."
Close of Day. returns = returnedGoods + cancellations + removedWithoutRefund. The parts are shown in sales.detail:
returnedGoods: for each refund line whoserestockTypeis notCANCEL, −RefundLineItem.subtotalSet(less itstotalTaxSetwhen prices include tax), dated atRefund.processedAt.cancellations: the same, for refund lines whoserestockTypeisCANCEL.enums/RefundLineItemRestockType: CANCEL is "The refund line item was canceled. Use this when restocking unfulfilled line items."removedWithoutRefund: units that left the order with no refund line, counted asquantity − currentQuantity − units refunded. Each unit is valued at its share of the line's net, dated atcancelledAtif the order was cancelled, else at the sale.- Shipping, tax, duty and fee reversals stay in their own lines (Shipping, Taxes, Duties, Additional fees). This keeps the brief's Shipping and Taxes formulas whole.
Brief: "returns are dated when the refund is processed, not when the sale was made". Confirmed.
Corrected: the name and the scope.
- Shopify now calls the line "Sales reversals", and it covers cancellations and edits as well as returned goods.
- Close of Day keeps the label Returns, as the brief asked. It includes cancellations and removals, and shows each separately.
- Shopify's Sales reversals also include "adjustments to shipping, taxes, fees, and discounts". Close of Day shows those inside Shipping, Taxes and Additional fees instead.
- So Close of Day's Returns will be smaller than Shopify's Sales reversals whenever shipping, tax or fees were reversed. Total sales is the same either way.
- Exactly how Shopify splits these is Unconfirmed.
Net sales — sales.netSales
- Shopify, Sales report: "gross sales - discounts - sales reversals"
- Shopify, Finances report: "gross sales - discounts - sales reversals. Net sales does not include shipping charges or taxes."
- Close of Day: grossSales + discounts + returns. The last two are negative.
- Brief: "net sales is gross minus discounts minus returns". Confirmed.
Shipping — sales.shipping
- Shopify, Sales report: "shipping charges - shipping discounts - refunded shipping amounts"
- Shopify, Finances report: Shipping charges: "The shipping charges associated with a sale or return."
- Close of Day: shippingCharged + shippingDiscounts + shippingRefunded, shown in
sales.detail:shippingCharged:ShippingLine.originalPriceSet, on the sale date.objects/ShippingLine, paraphrase: "Shipping price without discounts; includes taxes if parent order hastaxesIncludedtrue, otherwise pre-tax."shippingDiscounts: −(the shipping line'sdiscountAllocations), on the sale date.shippingRefunded: −RefundShippingLine.subtotalAmountSet, lesstaxAmountSetwhen prices include tax, on the refund date.
- Brief: "shipping is shipping charged minus shipping discounts minus shipping refunded". Confirmed.
Taxes — sales.taxes
Shopify
- Sales report: "The total amount of taxes based on the orders."
- Finances report: Taxes: "The taxes associated with a sale or return."
- Finances report, Taxes: "If a refund is processed for a line item, then only the tax that's associated with that line item is refunded."
- Finances report, US note: "In the country and jurisdiction summary views, the tax amount is reduced by the amount of the refund".
- Sales reversals include "adjustments to … taxes" (above).
Close of Day. taxesCharged + taxesReversed, shown in sales.detail:
taxesCharged: the sum ofTaxLine.priceSeton product lines and shipping lines, on the sale date.objects/TaxLine: priceSet is "The amount of tax, in shop and presentment currencies, after discounts and before returns."taxesReversed, which is negative and has three parts:- −
RefundLineItem.totalTaxSetand −RefundShippingLine.taxAmountSet, on the refund date - the prorated tax of units removed without a refund, on the removal date
- −
- Tax on gift card lines and tip lines is not counted, because those lines are not sales (Close of Day's own).
Brief: "taxes are net of refunded taxes". Confirmed by the Finances report's "associated with a sale or return" and the refund rule quoted above. The Sales report does not say it in those words.
Duties — sales.duties
- Shopify, Sales report: "The total amount of duties based on the orders." Also: "Duties display by default only on applicable reports for stores that have activated duties collection at checkout."
- Close of Day: dutiesCharged + dutiesRefunded:
dutiesCharged:Order.originalTotalDutiesSet("The total amount of duties calculated when an order was created, before any modifications."), on the sale datedutiesRefunded: −(the sum ofRefundDuty.amountSet), on the refund date
- Brief: "duties … if the data carries them". They are carried when the order has them. Zero otherwise.
Additional fees — sales.additionalFees
Shopify
objects/AdditionalFee: "Additional fees applied to an Order beyond the standard product and shipping costs. Additional fees typically include duties, import fees, or other special handling charges that need separate tracking from regular LineItem objects."- Finances report: Return fees: "The value that you charge your customers for returning goods, such as restocking fee or return shipping fee."
Close of Day. feesCharged + feesReversed:
feesCharged:Order.originalTotalAdditionalFeesSet("The total amount of all additional fees that were applied when an order was created. Returns null if additional fees aren't applicable."), on the sale date.feesReversed: −(original −currentTotalAdditionalFeesSet), where current is "The current total of all additional fees for an order, after any returns or modifications." It is posted on the latest refund's date, or on the sale if there is no refund.
Brief: "additional fees if the data carries them". Carried. How the reversal is dated is Unconfirmed. Return fees are not modelled.
Refund adjustments — sales.refundAdjustments
Shopify
objects/OrderAdjustment: "An order adjustment accounts for the difference between a calculated and actual refund amount."- REST refund resource: "Order adjustments are generated to account for refunded shipping costs and differences between calculated and actual refund amounts." Its example amount is
"10.00", a positive number.
Close of Day (own line)
- The sum of
OrderAdjustment.amountSet + taxAmountSeton each refund, on the refund date, taken with the sign Shopify sends. - It is added to total sales so that money refunded beyond, or short of, the itemised refund is not lost.
- Its sign, and whether Shopify's total sales includes it, are Unconfirmed.
Total sales — sales.totalSales
Shopify
- Sales report: "gross sales - discounts - sales reversals + taxes + duties + shipping charges + fees"
- Analytics fields: "Formula: net sales + additional fees + duties + shipping charges + taxes"
- Finances report, two fetches:
- "gross sales - discounts - sales reversals + taxes + shipping charges + fees."
- "The total sales value equates to gross sales - discounts - sales reversals + taxes + shipping + fees."
Close of Day. netSales + shipping + taxes + duties + additionalFees + refundAdjustments.
Brief: "total sales is net plus taxes plus shipping, plus duties and additional fees".
- Confirmed by the Sales report and the analytics field.
- The Finances report's formula leaves duties out. Close of Day follows the Sales report and includes them.
- Close of Day also adds refund adjustments, which is Close of Day's own choice (Unconfirmed).
Paying with a gift card
Shopify, Sales report
- When a customer uses a gift card: "It's included in sales reports. The full value of the item is claimed as sales."
- "The amount paid by gift card is subtracted from the gift card balance, which is displayed in the Outstanding gift card balance finance report."
Shopify, Finances report. "The amount paid by gift card is included in the Payments finance report as a gift card entry."
Close of Day
- Sales are built from the order's lines and never look at how the order was paid.
- The gift card payment appears under Payments as the
gift_cardgateway, and asliabilities.giftCardsRedeemed.
Brief: "paying with a gift card does not reduce sales". Confirmed.
Test orders
- Shopify, Sales report: "Test orders aren't included."
- Shopify, Sales discrepancies: "Test orders aren't included in Sales reports but they're included in your orders export."
- Shopify,
objects/Order: test is "Whether the order is a test. Test orders are made using the Shopify Bogus Gateway or a payment provider with test mode enabled. A test order can't be converted into a real order and vice versa." - Close of Day:
- The search asks for
test:false, andsummarisedrops any record withtest: true. - It also drops any transaction with
test: true. That is Close of Day's own choice.
- The search asks for
- Brief: "test orders are excluded". Confirmed.
Which day a sale belongs to
Shopify
- Sales report: "Sales display in your sales reports as a positive value for the day that they were made".
- Sales report, Orders: "The number of orders that were placed on a given date."
objects/Order: processedAt is "The date and time in ISO 8601 format when the order was processed. This date and time might not match the date and time when the order was created."- No page fetched names the timestamp or the time zone the reports use. The ShopifyQL TIMEZONE modifier "calculates the time-based results in your report in the selected timezone", but its default is not given.
Close of Day. Order.processedAt (fallback createdAt), read in Shop.ianaTimezone.
Brief: "sales are dated by the order's processed time in the store's time zone". Neither confirmed nor contradicted. Close of Day does what the brief says, and it is listed as Unconfirmed.
A cancelled order that was refunded
Shopify, Sales report
- "Pending, unpaid, and canceled orders are included in the reports."
- Sales reversals include "order cancellations".
Close of Day
- The sale is posted on its own date.
- The refund's lines with
restockTypeCANCEL are posted ascancellations, a part of Returns, on the refund date. Their tax and refunded shipping go to Taxes and Shipping. - A cancellation that refunded nothing is reversed through
removedWithoutRefundoncancelledAt.
Brief: "a cancelled order that was refunded shows as a sale and as a return". Confirmed, with Shopify's name for it: a sales reversal.
Order count — sales.orderCount
- Shopify, Sales report: "The number of orders that were placed on a given date."
- Shopify, Analytics fields: "Number of orders placed".
- Close of Day:
- the number of non-test orders whose sale is dated in the bucket
- cancelled orders are counted
- an order with only gift card lines is counted (Unconfirmed whether Shopify counts it)
Refund count — sales.refundCount
- Close of Day's own. The number of
Refunds whose date falls in the bucket. No Shopify definition was found for a refund count. The Sales report's "Returns" count is deprecated in favour of Sales reversals.
Payments
Per gateway — payments.byGateway[]
Shopify, Finances report
- Payments are grouped by "Payment method", among other groupings.
- The figures are "Transactions", "Gross payments", "Refunds" and "Net payments".
- Net payments: "total amount paid - the total amount refunded".
- Gross payments: "The amount paid by the transactions before refunds."
- "If you mark an order as paid and select Other as the payment method, then the report displays the payment method as Manual".
Shopify, API
objects/OrderTransaction:- gateway: "The payment gateway used to process the transaction."
- formattedGateway: "The human-readable payment gateway name used to process the transaction."
- processedAt: "Date and time when the transaction was processed."
- test: "Whether the transaction is a test transaction."
enums/OrderTransactionKind:- SALE: "An authorization and capture performed together in a single step."
- CAPTURE: "A transfer of the money that was reserved by an authorization."
- REFUND: "A partial or full return of captured funds to the cardholder. A refund can happen only after a capture is processed."
- CHANGE: "The money returned to the customer when they've paid too much during a cash transaction."
- AUTHORIZATION: "An amount reserved against the cardholder's funding source. Money does not change hands until the authorization is captured."
- VOID: "A cancelation of an authorization transaction."
enums/OrderTransactionStatus: SUCCESS is "The transaction succeeded."
Close of Day. Only transactions with status SUCCESS and test false count. Each is dated at its processedAt and grouped by gateway; the label is formattedGateway.
| Kind | Effect |
|---|---|
| SALE, CAPTURE | collected += amount |
| CHANGE | collected −= amount |
| REFUND | refunded −= amount |
| AUTHORIZATION, EMV_AUTHORIZATION, VOID, SUGGESTED_REFUND | skipped |
net = collected + refunded.
Brief: "per gateway, net of refunds, dated by transaction processedAt". Implemented as asked. That Shopify's Payments report dates by processedAt is Unconfirmed.
Total payments — payments.total
- Close of Day: the sum of every gateway's
net. This is Net payments as the Finances report defines it.
Reconciliation — payments.reconciliation
Shopify
- Finances report: "There could be differences between the values displayed on each report, for example if customers have placed orders but payment has not yet been captured".
- Sales discrepancies: "Sales reports include your returns and the Payments finance report includes refunds."
Close of Day
- Labelled "Timing or outstanding difference".
- Shows
salesMinusPayments= totalSales − payments, as the brief asked. - Shows
difference= totalSales + giftCardsSold + tips − payments.
Brief: "total sales minus payments collected, labelled as the timing or outstanding difference". Corrected:
- Payments also carry money that is not in total sales: the price of gift cards sold ("Selling a gift card isn't counted as a sale because it's a liability", Finances report) and tips.
- So on a day when everything is paid, totalSales − payments is not zero. It is off by exactly the gift cards and tips sold.
differenceadds those back, so it is zero when every sale is paid and nothing is outstanding.- Both figures are given.
- That a gift card's purchase price is in Payments is inferred, not quoted (Unconfirmed). For tips, Checkout tips says they are "part of the order total".
Cash over / short
The whole store's "Cash over / short" line is the sum over every register session that closed that local day (the day of the session's closing time in the store's zone) of counted cash minus expected cash, where expected is Shopify's expectedClosingBalance falling back to expectedBalance and counted is closingBalance. Open sessions add nothing. A short count is negative.
It is not a Payments-report line; Shopify's Finances summary has no equivalent. It is shown so the day's cash can be tied to the till. totalDiscrepancy (which includes the opening difference) is stored but not summed.
Unconfirmed: that expectedClosingBalance is always set on a closed session; the fallback covers the case where it is not.
Liabilities
Gift cards sold — liabilities.giftCardsSold
Shopify
- Finances report: Net sales from gift cards: "the face value of sold gift cards minus any discounts". A second fetch gave "Gift card sales revenue, with discounts and sales reversals factored in".
- Finances report: "Selling a gift card isn't counted as a sale because it's a liability."
- Sales report: "It isn't included in any sales reports, nor the total sales number in the Home analytics card."
Close of Day. Lines with LineItem.isGiftCard ("Whether the line item represents the purchase of a gift card."):
- their net (original − discounts) on the sale date
- less refunded gift card lines on the refund date
- less removed units
They are never in gross sales.
Brief: "gift cards sold (kept out of gross)". Confirmed.
Gift cards redeemed — liabilities.giftCardsRedeemed
- Shopify, Finances report: "The amount paid by gift card is included in the Payments finance report as a gift card entry."
- Close of Day: the
netof the gateway namedgift_card(GIFT_CARD_GATEWAY). That this is the gateway string Shopify uses is Unconfirmed: no page fetched gave an example.
Tips — liabilities.tips
Shopify
- Finances report: "The total value of tips received".
- POS tips: "You can view the tips collected by each of your staff in your Tips report, and the total tips collected in your Finances report."
- Checkout tips: "The tip is calculated on the cart's subtotal before taxes and shipping. However, tips are subject to credit card fees or third-party transaction fees because they're part of the order total."
objects/Order: totalTipReceivedSet is "The sum of all tip amounts for the order, in shop and presentment currencies."
Close of Day
- The net of the order's tip lines on the sale date, less refunded tip lines on the refund date.
- If no tip line is found,
totalTipReceivedSetis used instead, with a warning.
How a tip line is found:
- A line is a tip when it is not a gift card, its
skuandvendorare null, its title or name is "Tip" (in any case), and the order'stotalTipReceivedSetis above zero. - If no line is named "Tip", a single bare line whose amount equals the tip is taken, with a warning.
- The source is a Shopify staff answer on community.shopify.dev (
/t/how-to-identify-a-tip-line-item-with-graphql-order-api/14425, 2025-05-01): "while there isn't a field for TIP on the line item, I do notice that fields like product and sku will return NULL on the line item". Its example line is"name": "Tip". - Product is not read, because Close of Day does not ask for
read_products.
Tips are kept out of gross sales and total sales. That is inferred, not quoted:
- gross is "product selling price x ordered quantity", and a tip line has no product
- the API keeps
TipSaleapart fromProductSale(interfaces/Sale) - the Finances report shows tips on their own cards
It is Unconfirmed.
Tax detail — tax
Taxable and non-taxable sales — tax.taxableSales, tax.nonTaxableSales
Shopify. No definition was found. The Taxes finance report's columns are "Sales channel," "Tax country," "Tax region," "Tax name," "Filed by channel," "Tax rate," "Sales taxes". The tax-reports page does not list taxable or non-taxable sales.
Close of Day's own
- A product line is taxable when its tax lines charged more than zero.
- Taxable sales is the net of taxable lines, after discounts, returns and removals. Non-taxable sales is the net of the others.
- taxableSales + nonTaxableSales = netSales, which the tests check on every day.
- Shipping is in neither.
LineItem.taxable("Whether the variant is taxable.") is not used. Close of Day goes by the tax actually charged.
Tax by rate — tax.byRate[]
Shopify
objects/TaxLine: title is "The name of the tax." rate is "The proportion of the line item price that the tax represents as a decimal." ratePercentage is "The proportion of the line item price that the tax represents as a percentage."- Taxes report columns "Tax name", "Tax rate", "Sales taxes".
Close of Day. One row per (title, rate):
taxableBase: the net of every product line and shipping line that carries that tax line. A line taxed at two rates is in both bases. Shipping is in the base of the rates charged on it, though not in taxable sales.tax:- the sum of
TaxLine.priceSet - less refunded tax, split across the line's original tax lines in proportion to what each charged (largest remainder, so the parts sum exactly)
- less the prorated tax of removed units
- the sum of
- Refunded tax on a line the query did not return goes to a row titled "Unattributed".
- The rows'
taxsums to Taxes, which the tests check on every day.
Drill-down
orders: the ids of every order with any event in the bucket: a sale, a refund, a removal or a payment.refunds: the ids of the refunds dated in the bucket.
Close of Day's own.
The query
src/orders.mjs exports these. Every field and argument in them was found on the 2026-07 reference page named.
ORDERS_QUERY
orders(first: $first, after: $after, query: $query, sortKey: PROCESSED_AT)withpageInfo { hasNextPage endCursor }andnodes.queries/orderslistsfirst,after,queryandsortKey(default PROCESSED_AT).connections/OrderConnectionlistsnodesandpageInfo.objects/PageInfo: hasNextPage is "Whether there are more pages to fetch following the current page."; endCursor is "The cursor corresponding to the last node in edges."
ORDER_QUERY. order(id: $id) with the same order fields. From queries/order: "id: ID! (required)".
SHOP_QUERY. shop { ianaTimezone }, from objects/Shop.
ordersSearchQuery. Builds test:false processed_at:<'END' updated_at:>='START':
- The instants are written in UTC with a
Z, and quoted, asusage/search-syntaxrequires: "Date values must be a string surrounded by quotes." Its example iscreated_at:>'2020-10-21T23:39:20Z'. queries/orderslistsprocessed_at("Filter by the order processedAt field"),updated_atandtest.
Fields asked for, by object:
| Object | Fields | Page |
|---|---|---|
| Order | id, name, processedAt, createdAt, cancelledAt, test, sourceName, currencyCode, taxesIncluded, retailLocation, totalTipReceivedSet, totalTaxSet, totalDiscountsSet, originalTotalDutiesSet, originalTotalAdditionalFeesSet, currentTotalAdditionalFeesSet, lineItems(first), shippingLines(first), refunds(first), transactions(first) | objects/Order |
| Location | id, name | objects/Location |
| MoneyBag / MoneyV2 | shopMoney / amount | objects/MoneyBag, objects/MoneyV2 |
| LineItem | id, name, title, sku, vendor, quantity, currentQuantity, isGiftCard, originalTotalSet, discountAllocations, taxLines | objects/LineItem |
| DiscountAllocation | allocatedAmountSet | objects/DiscountAllocation |
| TaxLine | title, rate, ratePercentage, priceSet | objects/TaxLine |
| ShippingLine | id, title, originalPriceSet, discountAllocations, taxLines | objects/ShippingLine |
| Refund | id, createdAt, processedAt, refundLineItems(first), refundShippingLines(first), orderAdjustments(first), duties, transactions(first) | objects/Refund |
| RefundLineItem | id, quantity, restockType, lineItem { id }, subtotalSet, totalTaxSet | objects/RefundLineItem |
| RefundShippingLine | id, shippingLine { id }, subtotalAmountSet, taxAmountSet | objects/RefundShippingLine |
| OrderAdjustment | id, reason, amountSet, taxAmountSet | objects/OrderAdjustment |
| RefundDuty | amountSet | objects/RefundDuty |
| OrderTransaction | id, kind, status, gateway, formattedGateway, test, processedAt, createdAt, amountSet, location { id } | objects/OrderTransaction |
Never asked for:
- customer, address, email, phone and note fields
- product and variant:
objects/Product"Requiresread_productsaccess scope."
Self-checks in normaliseOrder. Each mismatch is a warning, not an error:
- tax lines against
Order.totalTaxSet("The total tax amount before returns, in shop and presentment currencies.") - discount allocations against
Order.totalDiscountsSet
Cost, page size and truncation
Shopify (https://shopify.dev/docs/apps/build/apis/graphql-admin/rate-limits):
- "A single query may not exceed a cost of 1,000 points, regardless of plan limits."
- The cost table: Scalar 0, Enum 0, Object 1, Connection "Sized by
firstandlastarguments", Mutation 10. - "The requested cost is based on the composition of fields selected in the request. The actual cost is based on the query results".
- "Running a query is the best way to find out its true cost".
- The page says nothing about lists that are not connections.
Close of Day's estimate, in the test estimatedCost:
- a connection costs 1 for itself and its pageInfo, plus
first× (1 + a node's cost) - a plain list with
first(Order.refunds,Order.transactions) costsfirstelements - a plain list without
firstcosts one element
The figures are:
| Query | Size | Estimated cost |
|---|---|---|
| ORDERS_QUERY | ORDERS_PAGE_SIZE = 5 orders, with LIMITS | 927 |
| ORDER_QUERY | one order, with ORDER_LIMITS | 923 |
At the first draft's 25 orders and larger lists, the same estimate was about 73,000. So the page size and nested lists were cut.
| List | LIMITS (ORDERS_QUERY) | ORDER_LIMITS (ORDER_QUERY) |
|---|---|---|
| lineItems | 6 | 30 |
| shippingLines | 1 | 3 |
| refunds | 2 | 4 |
| refundLineItems (per refund) | 3 | 15 |
| refundShippingLines (per refund) | 1 | 2 |
| orderAdjustments (per refund) | 1 | 3 |
| refund transactions (per refund) | 1 | 3 |
| transactions | 5 | 20 |
How a list is marked as possibly cut short, in truncated:
- a connection:
pageInfo.hasNextPage - a plain list (refunds, transactions): it came back as long as its limit
The worker (D3) re-reads an order with any flag set through ORDER_QUERY, and normalises it with normaliseOrder(node, ORDER_LIMITS). An order still flagged after that is summed with a warning that it may be incomplete.
Access scopes
- Orders.
queries/ordersays: "Only the last 60 days' worth of orders from a store are accessible from theOrderobject by default." It listsread_ordersandread_all_orders. A range older than 60 days needsread_all_orders, whichshopify.app.tomldoes not yet ask for. - Locations.
objects/Locationneedsread_locations,read_inventoryorread_markets_home.read_locationsis configured. - Cash tracking.
read_cash_trackingreadsCashTrackingSessionandCashDrawer; data is returned only for locations with a POS Pro subscription. Built: the drawer section readsCashTrackingSessiononly, 25 sessions and 10 adjustments a request for the query cost limit, and nevercashTransactions, a staff member field, or an opening or closing note.
Unconfirmed
Each item is an assumption Close of Day makes because no Shopify page that was read settles it. The assumption is stated after each name.
Dating and the search
- Sale date and time zone. Assumed: Shopify's reports date a sale by
Order.processedAtin the store's IANA time zone. The pages say only "for the day that they were made" and "placed on a given date". - Payment date. Assumed: the Payments report dates a payment by
OrderTransaction.processedAt. - Refunds and payments touch
updated_at. Assumed: a refund or transaction on an old order moves that order'supdated_at, soupdated_at:>=STARTfinds it. test:false. Assumed to be accepted.queries/ordersgives the filter's type as boolean but only showstest:true. The engine drops test orders again either way.- Search time zone. Avoided rather than assumed: instants are written in UTC with a
Z. The search's default time zone for a bare date is not stated.
Payments and gateways
- Gateway strings. Assumed: a gift card payment has
gatewaygift_card. No page fetched showed gateway values for gift card, cash or Shopify Payments. - Transaction amount sign. Assumed:
OrderTransaction.amountSetis positive for every kind, with the kind giving the direction. - CHANGE. Assumed: a CHANGE transaction is cash handed back and is taken off the money collected.
- Labels. Assumed:
formattedGatewayis close to the report's payment method label. The report shows "Manual" for Other, and Close of Day does not map that. - Gift cards sold in Payments. Assumed: the money taken for a gift card sold appears in Payments, which is why the reconciliation adds gift cards sold back.
Discounts and tax totals
- Order-level discounts in
discountAllocations. Assumed:LineItem.discountAllocationsincludes the line's share of order-level discounts.LineItem.totalDiscountSet, in one fetch: "This value doesn't include order-level discounts". Close of Day sumsdiscountAllocationsinstead, and warns when they do not matchtotalDiscountsSet. Order.totalTaxSet. Two fetches disagreed:- "The total tax amount before returns, in shop and presentment currencies."
- "The sum of the prices of all tax lines applied to line items on the order, after returns and refunds, …", which matches
currentTotalTaxSet's own description.
Assumed: before returns. Whether it counts shipping tax is not stated, so the self-check accepts either.
Order.totalDiscountsSet. Two fetches disagreed: "before returns … This includes both order and line level discounts", and a table reading "after returns/refunds". Assumed: before returns. Whether it counts shipping discounts is not stated, so the self-check accepts either.
Refunds, prices with tax, edits and cancellations
RefundLineItem.subtotalSet. Assumed: it is after the line's discounts, and includes tax when the order's prices include tax. Its description is only "The subtotal price of a refunded line item".RefundShippingLine.subtotalAmountSet. Assumed: it includes tax when the order's prices include tax.- Gross on tax-inclusive orders. Assumed: Shopify reports gross sales without the tax inside the price. Close of Day scales gross by net ÷ discounted total.
- Units removed without a refund. Assumed: they come off on
cancelledAt, or on the sale date for an edit. Shopify's sales agreements (interfaces/SalesAgreement,happenedAt) would give the exact date, but are not queried. Shopify's report shows an edit made on a later day "as a separate order on the Total sales over time report". - Removed shipping lines. Not queried.
shippingLinestakesincludeRemovals, and its default is not stated. - A cancellation and its refund. Assumed: a cancelled and refunded order carries a Refund whose lines have
restockTypeCANCEL. - Restock types. Assumed: RETURN, NO_RESTOCK and LEGACY_RESTOCK are all returned goods.
- Restock without refund. Not modelled. Shopify notes tax "might display as a return amount" in that case.
Tips
- The tip line rule. It comes from a community answer, not the reference.
- Tips out of gross and total sales. Inferred, not quoted.
- POS tips. Whether a POS tip is a line item like a checkout tip is not stated. If it is not, the
totalTipReceivedSetfallback applies. - Refunded tips. Whether
totalTipReceivedSetis net of refunded tips is not stated. A refunded tip is taken from its refund line, when there is one.
Gift cards
- Gift-card-only orders. Assumed: they count in the order count.
Fees, duties and adjustments
- Fee reversal date. Assumed: a reversal of additional fees (original − current) belongs on the latest refund's date.
- Fee taxes.
AdditionalFee.taxLinesis not queried. - Fees and duties overlap. Assumed:
originalTotalAdditionalFeesSetandoriginalTotalDutiesSetdo not overlap, although AdditionalFee "typically include[s] duties". - OrderAdjustment sign and inclusion. Assumed:
amountSetcarries its own sign, and the adjustment belongs in total sales. The REST example shows"10.00". - Not modelled: return fees, cash rounding ("Rounding adjustment applied on a sale or refund cash transaction"), store credit, and exchanges.
Locations
- Return location. Assumed: a return belongs to the location of its refund's transaction, else the order's. The Retail sales page does not say.
- Refund transactions beyond the limit. A refund's location is looked up among the order's own transactions. If those were cut short, it falls back to the order's location.
Close of Day's own rules
- Taxable sales. Assumed: "taxable" means tax was charged.
- Rate base. Assumed: the rate base includes shipping.
- Refund count. Assumed: it counts Refunds.
The query and the data
- Connection shape.
nodesandpageInfoon LineItemConnection, ShippingLineConnection, RefundLineItemConnection, RefundShippingLineConnection, OrderAdjustmentConnection and OrderTransactionConnection were confirmed on OrderConnection only. They are assumed to be the same. - The cost model. Assumed:
- a connection's own cost (1, with its pageInfo)
- that
firstsizes the plain listsrefundsandtransactions - that a list without
firstcosts one element:LineItem.taxLines, which takesfirstwith no stated default;discountAllocations;Refund.duties
If Shopify costs these lists higher,
ORDERS_PAGE_SIZEor the limits must come down.extensions.cost.requestedQueryCoston the first real response settles it. - List lengths. Assumed: an order rarely has more than 6 line items or 5 transactions. Past that it costs one extra request.
- Currency precision. Taken from
Intl(CLDR), not from Shopify. - physicalLocation. Deprecated. The reason was not shown, and
retailLocationis used. - Source wording. The quotes came through a fetch tool that summarises.
ShippingLine.originalPriceSetis a paraphrase.
The 2026-10 release notes
- Tax recalculated after a shipping-address change. The 2026-10 release notes (https://shopify.dev/changelog/release-notes/2026-10), under Orders, "Action required": "Changing the shipping address on an unfulfilled order with
orderUpdateor the REST Admin API order update endpoint now recalculates taxes for the new destination. After updating, query updatedtaxLines,totalTaxSet, totals, and compare balances to handle payment or refund differences." The notes rename, remove and deprecate nothing Close of Day reads. Close of Day sums the currenttaxLineson the sale date, so if a later address change rewrites them, the sale day's taxes and total sales change after the fact instead of a difference being posted on the day of the change. Not stated: how Shopify's own reports show this; how the difference is recorded (a refund, an adjustment, or rewritten lines); and whether the version of the app that updates the order or the version Close of Day reads with decides. Assumed: the tax lines read are the current ones, whatever version wrote them.