SHOP DESKDevelopers
shopdeskbd.com

Sales and reports

The sales summary, comparisons and top products, and what each figure counts.

"How were sales this week?" is the first thing a merchant asks an assistant, and the first number a BI tool wants. This guide covers the two report endpoints, what each figure counts, and which plan each needs.

You need a key with reports:read. It is flagged sensitive when you create the key, because it reveals the store's sales.

EndpointPlan
GET /reports/sales-summaryEvery plan with API access
GET /reports/sales-summary?compare=previous_periodAdvanced Reports
GET /reports/top-productsAdvanced Reports

A plan without Advanced Reports gets 403 with the code PLAN_FEATURE_REQUIRED on the last two, and the summary still works. That code means the plan, not the key, is missing something: a key without reports:read gets FORBIDDEN_SCOPE instead. See Errors.

Each call to either endpoint counts as 5 reads against the key's read limit, because a report is several queries. See Rate limits.

Windows

Both endpoints take from and to: the first and last day of the window, inclusive, as the store's calendar days (2026-09-01). With neither, the window is the current month so far. A window spans at most 366 days. The store's timezone is echoed as time_zone, and GET /store returns it as timezone.

Instead of from and to, you can name the window with period: today, yesterday, last_7_days (today and the six days before), last_30_days, this_month (the 1st to today) or last_month. It is read on the store's calendar, so "yesterday" is the store's yesterday, and the response echoes the concrete from and to. Sending period with from or to is a 422.

A company-scoped key must name the store with store_id. A report answers for one store.

Answers are cached for 5 minutes per store and window, so polling faster than that returns the same figures.

The sales summary

export SHOPDESK_API_KEY="shopdesk_sk_YOUR_API_KEY"

curl -sS "https://api.shopdeskbd.com/ext/v1/reports/sales-summary?from=2026-09-01&to=2026-09-30" \
  -H "Authorization: Bearer $SHOPDESK_API_KEY"

The figures are the same numbers the dashboard's Reports pages show for the same window. They run on three different clocks, and basis says which:

FieldCountsbasis
ordersOrders delivered in the windowsales: delivered
gross_salesTheir line value after markdowns, before coupons and deliverysales: delivered
net_salesWhat those customers were billed for goods and delivery, excluding taxsales: delivered
net_revenuenet_sales less returned goods, refunds, whole-order returns and courier concessionssales: delivered
average_order_valuenet_sales ÷ orderssales: delivered
money_receivedPayments settled in the window, whichever order they belong tomoney_received: settled
cod_outstandingWhat open orders still owe as of today: not shipped, with the courier, delivered but unpaidcod_outstanding: as_of_today

An order placed on the 30th and delivered on the 2nd counts in the next month's sales, which is when the sale became final. Don't add money_received to net_sales: they measure different things.

money_received leaves out payments on orders that are cancelled or returned now. If an order paid in a past window is cancelled or returned later, that window's money_received goes down, exactly as the dashboard's Payments report does. Store a closed month's figure yourself if you need it frozen.

By channel. Pass channel (a slug from GET /channels) to count only that channel's sales. money_received and cod_outstanding are then null, because payments are not split by channel.

Comparing with the previous period

export SHOPDESK_API_KEY="shopdesk_sk_YOUR_API_KEY"

curl -sS "https://api.shopdeskbd.com/ext/v1/reports/sales-summary?from=2026-09-22&to=2026-09-28&compare=previous_period" \
  -H "Authorization: Bearer $SHOPDESK_API_KEY"

compare=previous_period adds previous_period: the same figures for the window of equal length that ends the day before from. A week compares with the week before it. A 30-day month compares with the 30 days before it, not with the previous calendar month.

Top products

export SHOPDESK_API_KEY="shopdesk_sk_YOUR_API_KEY"

curl -sS "https://api.shopdeskbd.com/ext/v1/reports/top-products?from=2026-09-01&to=2026-09-30&limit=10" \
  -H "Authorization: Bearer $SHOPDESK_API_KEY"

Product variants ranked by the revenue of the units delivered in the window that customers kept. Returned units are netted out and shown as units_returned. limit is 1–50, default 10.

With the store MCP server

An assistant connected to the store MCP server answers "how were sales this week?" with one tool call: get_sales_summary takes period (or from/to), compare_to: "previous_period" and channel, and returns the same figures as GET /reports/sales-summary with the same basis. It answers concisely by default — the headline figures and the COD total — and with response_format: "detailed" it returns the full REST body, stage split included. The same plan rules apply: comparisons need Advanced Reports.

A call counts as 5 reads against the key's read limit, the same as the REST endpoint. A comparison on a plan without Advanced Reports comes back as an error with the code PLAN_FEATURE_REQUIRED. The ranking has no tool: a BI sync reads GET /reports/top-products over REST.