Reports
Sales figures for a window: a summary on every plan with API access; comparisons and top products with Advanced Reports.
Paste a key and every snippet on this page switches from the placeholder to your key — and the Try it panel under each endpoint is ready to send. It is stored in this browser only and goes nowhere except, if you press Send, straight to the API host you pick there.
Get a sales summary for a window
/ext/v1/reports/sales-summaryreports:readOrders, gross and net sales, net revenue and average order value for the orders DELIVERED in the window, the money received (payments settled in the window) and the cash on delivery still to collect (as of today) — each figure the same number the Reports pages in the dashboard show, with its basis stated in basis. Available on every plan with API access; compare=previous_period needs Advanced Reports. The window spans at most 366 days; answers are cached for 5 minutes. A call counts as 5 reads against the key's read limit. Company-scoped keys must pass store_id.
Query parameters
| Name | Type | Description |
|---|---|---|
period | string | A named window instead of from/to, resolved on the store's own calendar: today, yesterday, last_7_days (today and the six days before), last_30_days, this_month (the 1st to today) or last_month. The response echoes the concrete from and to. Not combinable with from or to.todayyesterdaylast_7_dayslast_30_daysthis_monthlast_month |
from | string | First day of the window (inclusive, a store-local calendar day). Defaults to the first day of the current month. |
to | string | Last day of the window (inclusive). Defaults to today. The window may span at most 366 days. |
store_id | uuid | The store to report on. REQUIRED with a company-scoped key (a report answers for one store); with a store-scoped key it may only repeat the key's own store. |
channel | string | Only this sales channel (its SLUG, from GET /channels). With a channel filter, money_received and cod_outstanding are null: payments are not split by channel. |
compare | string | previous_period adds previous_period: the same figures for the window of equal length just before. Needs a plan with Advanced Reports.previous_period |
Request
export SHOPDESK_API_KEY="shopdesk_sk_YOUR_API_KEY"
curl -sS "https://api.shopdeskbd.com/ext/v1/reports/sales-summary" \
-H "Authorization: Bearer $SHOPDESK_API_KEY"const url = new URL("https://api.shopdeskbd.com/ext/v1/reports/sales-summary");
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${process.env.SHOPDESK_API_KEY}`,
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.code}: ${error.message} [${error.request_id}]`);
}
const object = await response.json();import os
import requests
response = requests.get(
"https://api.shopdeskbd.com/ext/v1/reports/sales-summary",
headers={
"Authorization": f"Bearer {os.environ['SHOPDESK_API_KEY']}",
},
timeout=30,
)
if not response.ok:
error = response.json()["error"]
raise RuntimeError(f"{error['code']}: {error['message']}")
obj = response.json()<?php
$key = getenv('SHOPDESK_API_KEY');
$ch = curl_init('https://api.shopdeskbd.com/ext/v1/reports/sales-summary');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key],
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$response = json_decode($body, true);
if ($status >= 400) {
throw new RuntimeException("{$response['error']['code']}: {$response['error']['message']}");
}https://api.shopdeskbd.com/ext/v1/reports/sales-summary?period=last_7_days&from=2026-09-01&to=2026-09-30&channel=facebookStored in this browser only and never sent anywhere except to the API host you picked above — these pages are static files with no server behind them.
Query parameters
Blank fields are left out of the request.
Paste a key above to enable Send.
Responses
200The summary.401Missing/invalid API key, revoked or expired key, plan without API access, or a dead store.403FORBIDDEN_SCOPE: the key's scopes do not cover this endpoint.PLAN_FEATURE_REQUIRED:comparewas asked for on a plan without Advanced Reports.404Store not found (astore_idoutside this key).422Validation failed —error.fieldsmaps each offending field to its messages.429Rate limit exceeded for this key. HonorRetry-Afterand theX-RateLimit-*headers.
Every failure uses the one error envelope — Errors lists each code and what to do with it.
{
"from": "2026-09-01",
"to": "2026-09-30",
"orders": 42,
"gross_sales": "1250.00",
"net_sales": "1250.00",
"net_revenue": "1250.00",
"average_order_value": "1250.00",
"money_received": "1250.00",
"store_id": "5f7d2f60-0d1c-4b3a-9a68-6f4d21f6a001",
"time_zone": "Asia/Dhaka",
"channel": null,
"basis": {
"sales": "delivered",
"money_received": "settled",
"cod_outstanding": "as_of_today"
},
"cod_outstanding": {
"as_of": "2026-09-29",
"amount": "1250.00",
"orders": 11,
"not_shipped": {
"orders": 3,
"amount": "1250.00"
},
"with_courier": {
"orders": 3,
"amount": "1250.00"
},
"delivered_unpaid": {
"orders": 3,
"amount": "1250.00"
}
},
"previous_period": {
"from": "2026-09-01",
"to": "2026-09-30",
"orders": 42,
"gross_sales": "1250.00",
"net_sales": "1250.00",
"net_revenue": "1250.00",
"average_order_value": "1250.00",
"money_received": "1250.00"
}
}List the top products for a window
/ext/v1/reports/top-productsreports:readProduct variants ranked by the revenue of units delivered in the window and KEPT (returns netted) — the Products report ranking in the dashboard, with revenue and units only: no cost, profit or margin is ever returned. Needs a plan with Advanced Reports. The window spans at most 366 days; answers are cached for 5 minutes. A call counts as 5 reads against the key's read limit. Company-scoped keys must pass store_id.
Query parameters
| Name | Type | Description |
|---|---|---|
period | string | A named window instead of from/to, resolved on the store's own calendar: today, yesterday, last_7_days (today and the six days before), last_30_days, this_month (the 1st to today) or last_month. The response echoes the concrete from and to. Not combinable with from or to.todayyesterdaylast_7_dayslast_30_daysthis_monthlast_month |
from | string | First day of the window (inclusive, a store-local calendar day). Defaults to the first day of the current month. |
to | string | Last day of the window (inclusive). Defaults to today. The window may span at most 366 days. |
store_id | uuid | The store to report on. REQUIRED with a company-scoped key (a report answers for one store); with a store-scoped key it may only repeat the key's own store. |
limit | numberdefault 10max 50 | How many products to rank. |
Request
export SHOPDESK_API_KEY="shopdesk_sk_YOUR_API_KEY"
curl -sS "https://api.shopdeskbd.com/ext/v1/reports/top-products?limit=25" \
-H "Authorization: Bearer $SHOPDESK_API_KEY"const url = new URL("https://api.shopdeskbd.com/ext/v1/reports/top-products");
Object.entries({
limit: "25",
}).forEach(([key, value]) => url.searchParams.set(key, value));
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${process.env.SHOPDESK_API_KEY}`,
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.code}: ${error.message} [${error.request_id}]`);
}
const { data } = await response.json();import os
import requests
response = requests.get(
"https://api.shopdeskbd.com/ext/v1/reports/top-products",
params={
"limit": "25",
},
headers={
"Authorization": f"Bearer {os.environ['SHOPDESK_API_KEY']}",
},
timeout=30,
)
if not response.ok:
error = response.json()["error"]
raise RuntimeError(f"{error['code']}: {error['message']}")
page = response.json()
rows = page["data"]<?php
$key = getenv('SHOPDESK_API_KEY');
$ch = curl_init('https://api.shopdeskbd.com/ext/v1/reports/top-products?limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key],
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$response = json_decode($body, true);
if ($status >= 400) {
throw new RuntimeException("{$response['error']['code']}: {$response['error']['message']}");
}
$rows = $response['data'];https://api.shopdeskbd.com/ext/v1/reports/top-products?period=last_7_days&from=2026-09-01&to=2026-09-30Stored in this browser only and never sent anywhere except to the API host you picked above — these pages are static files with no server behind them.
Query parameters
Blank fields are left out of the request.
Paste a key above to enable Send.
Responses
200The ranking.401Missing/invalid API key, revoked or expired key, plan without API access, or a dead store.403FORBIDDEN_SCOPE: the key's scopes do not cover this endpoint.PLAN_FEATURE_REQUIRED: the plan does not include Advanced Reports.404Store not found (astore_idoutside this key).422Validation failed —error.fieldsmaps each offending field to its messages.429Rate limit exceeded for this key. HonorRetry-Afterand theX-RateLimit-*headers.
Every failure uses the one error envelope — Errors lists each code and what to do with it.
{
"store_id": "5f7d2f60-0d1c-4b3a-9a68-6f4d21f6a001",
"from": "2026-09-01",
"to": "2026-09-30",
"time_zone": "Asia/Dhaka",
"basis": {
"revenue": "delivered_kept"
},
"data": [
{
"product_id": "5f7d2f60-0d1c-4b3a-9a68-6f4d21f6a001",
"variant_id": "5f7d2f60-0d1c-4b3a-9a68-6f4d21f6a001",
"product_name": "Classic Cotton T-Shirt",
"variant_name": "Red / M",
"sku": "TSHIRT-RED-M",
"units_sold": 18,
"units_returned": 2,
"revenue": "1250.00"
}
]
}