The Shopify Reports API is a thin metadata layer: it lets you create, list, and delete the report definitions that show up on your admin's Reports page — it does not hand you the underlying sales, order, or profit data. The REST version of that resource was removed in a recent API release, and the REST Admin API itself is now legacy. If you run an operating store and want real numbers, you pull raw orders through the GraphQL Admin API (paginated queries, bulk operations, or ShopifyQL) and do the profit math yourself.

Most people who search "shopify reports api" expect an endpoint that returns their sales report as clean JSON. That is not what it is, and the gap between the expectation and the reality is where a lot of wasted engineering time goes. This walks through what the API actually does, why the old REST route is a dead end, and what an operator who already runs the numbers should build instead.

What the Shopify Reports API actually returns

The Reports resource was always a publishing API, not a data API. It managed the metadata for custom reports — a report's name, its category, and the query string that defined it — so a report would appear in your Shopify admin under Analytics. It never returned the rows of that report over HTTP.

In practice that means a call to the Reports endpoint hands you back a report object, not a table of orders. You learn that a report called "Sales by product" exists and which query powers it. You do not learn what the sales were. That single distinction is the thing the top-ranking tutorials tend to bury three sections deep.

So if your goal is "give me my revenue, refunds, and margin for last month," the Reports API is the wrong tool on its own. You would still have to go pull the order-level data separately and aggregate it. The report object is a pointer, not the payload.

Why the REST Reports resource is a dead end now

There is a second trap. The REST Admin API is a legacy API as of October 1, 2024, and Shopify's own documentation states that all new public apps must be built exclusively with the GraphQL Admin API beginning April 1, 2025. Building a fresh integration against the REST Reports resource today means building against something Shopify has already moved off of.

The REST Reports resource specifically was also retired from recent API versions, so the endpoint many older blog posts point you at simply is not there anymore. If you follow a 2022-era walkthrough, you will hit a wall. Treat any tutorial that centers the REST /admin/reports.json route as outdated.

This matters for awareness-stage research because the SERP is full of those older guides. They describe an endpoint that no longer behaves the way they claim. The practical takeaway: skip REST, and plan your reporting pull around GraphQL from day one.

The GraphQL path operators actually use

The real reporting workflow for an operating store is not one endpoint — it is a choice between three GraphQL tools, picked by how much data you move. Understanding which one fits your order volume saves you from rate-limit pain later. This is the same build-versus-buy question that sits under broader ecommerce business intelligence work.

Paginated orders queries

For a store moving a modest number of orders in the window you care about, you query the orders connection directly with a date filter and page through the results. According to a GraphQL reporting walkthrough from Rapid Developers, a single GraphQL query returns a maximum of two hundred fifty results per page, and you walk forward using cursor-based pagination.

You then aggregate revenue, refunds, and per-product totals on your own side. This is fine for a store doing a few hundred orders a month. It gets expensive fast once you are paging through tens of thousands of line items.

Bulk operations for large stores

When the pull is large, you switch to a bulk operation, which runs asynchronously and writes the full result set to a file you download. The same source notes the bulk mutation returns a JSONL file URL that stays valid for seven days and carries no rate-limit cost, with only one bulk operation allowed to run per shop at a time.

This is the right tool for a monthly or quarterly export of every order. You trigger the job, poll for completion, then ingest the file. No pagination loop, no points burned per page.

ShopifyQL for pre-aggregated analytics

The third route is ShopifyQL, Shopify's analytics query language, which runs against pre-aggregated tables and returns already-computed metrics instead of raw orders. A Shopify Community thread on using ShopifyQL through the API notes you need the read reports and read analytics scopes to run those queries. Availability and endpoint support for ShopifyQL have shifted across API versions, so confirm it against the version you are pinning before you depend on it.

ShopifyQL is attractive because it hands back totals without you reprocessing every order. The catch is the same one that runs through this whole topic: it gives you Shopify's view of the numbers, not your profit view.

The number the Reports API never gives you: profit

Here is the part every one of those ranking tutorials skips. Whether you pull raw orders or pre-aggregated ShopifyQL totals, Shopify reports revenue — it does not know your blank cost, your print fee, your shipping, your payment processing, or your ad spend. The report says you made money. It cannot tell you whether you kept any.

Walk a real example. Say you run a POD apparel store doing three hundred forty orders a month at a thirty-one dollar average order value — that is $10,540 in revenue, and it is exactly the number the Shopify Reports API surfaces.

Now net out what the report ignores, per order: a thirteen dollar blank-plus-print cost, five dollars of shipping, roughly a dollar and a quarter in payment fees, and about a dollar forty of pick-and-pack. That leaves $10.36 of contribution before advertising. Spread $2,800 of monthly Meta spend across those three hundred forty orders and you are adding about $8.24 of ad cost per order.

So your true per-order profit is $10.36 − $8.24 = $2.12. Across three hundred forty orders that is roughly $721 of contribution for the month — on top-line revenue the dashboard proudly reports as $10,540. The Reports API will never compute that $2.12, because every cost in that chain lives outside Shopify. This is the entire reason profit-focused performance analytics exist as a category separate from a store's native reports.

If you want the mechanics behind why that gap matters so much for a store buying traffic, the case for it is laid out in why analytics matters in ecommerce, and the forward-looking version of the same discipline shows up in these predictive analytics examples.

Build it yourself, or skip the pipeline

You can absolutely build the GraphQL pull, the bulk-export ingester, the COGS lookup, the ad-spend join, and the margin math yourself. It is a real project — scopes, version pinning, rate-limit handling, and a place to store and recompute the data every time a cost changes.

PodVector AI runs that pipeline for print-on-demand sellers so you do not have to stand it up. Victor is an AI employee that connects to your live Shopify store along with Meta Ads, Google Ads, Printify, Printful, Gelato, and Klaviyo, then computes your true per-order profit across all of them — the $2.12 the Reports API structurally cannot produce.

Victor is not a dashboard you log into and read. It works your live data, delivers reports to your Google Drive, and can draft approval-gated customer-support emails — and every write action it takes waits for your approval before anything runs. If you would rather skip the API build entirely, you can put Victor to work on your store.

FAQs

Does the Shopify Reports API return my actual sales data?

No. The Reports resource manages report definitions — a report's name, category, and query — so they appear on your admin's Analytics page. It returns metadata about reports, not the order rows or totals inside them. To get the underlying numbers you query orders through the GraphQL Admin API and aggregate them yourself.

Is the REST Reports API still available?

The REST Reports resource was removed in a recent API version, and the REST Admin API as a whole is legacy as of October 1, 2024, with new public apps required to use the GraphQL Admin API as of April 1, 2025. Build any new reporting integration against GraphQL. Old tutorials pointing at REST report endpoints are out of date.

What scopes do I need to pull reporting data?

For order-level pulls you typically request read orders; for ShopifyQL analytics queries you need the read reports and read analytics scopes. Request only what you use, since merchants see the scope list at install and over-asking lowers trust.

Should I use paginated orders queries or bulk operations?

Use paginated orders queries when you are moving a modest volume in the window — pages return up to two hundred fifty records and you cursor forward. Switch to bulk operations for large exports, since the bulk route carries no rate-limit cost and returns a downloadable file valid for seven days. A rough rule: if a paginated loop would run for many pages, use bulk.

Can the Shopify Reports API tell me if an order was profitable?

No, and this is the core limitation. Shopify knows revenue and its own fees, but not your blank cost, print charge, shipping, or ad spend, so it cannot compute contribution margin or true per-order profit. You have to join those external costs to the order data yourself — which is exactly the gap tools built for ecommerce analytics setup and measurement and profit platforms are designed to close.

How often can I pull report data without hitting limits?

GraphQL requests draw from a points bucket that refills over time, so the cadence depends on query cost and your plan. For heavy exports, bulk operations are the safe choice because they do not spend from that per-second budget. Schedule frequent light reads through paginated queries and reserve bulk jobs for full historical pulls.