> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alura.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Shop stats

> How get_my_shop_stats and GET /v1/workspace/stats count revenue, costs, profit and reviews from your Etsy payment ledger

> [!NOTE]
>
> **Version 2026-10.** This page defines every value of shop stats: `GET /v1/workspace/stats`, and `get_my_shop_stats` in an AI assistant. They are your shop's real finances, not estimates. They need the Financial reports permission in the workspace.

## Where the numbers come from

Shop stats come from your Etsy payment account's ledger: the entries Etsy books for sales, refunds, fees, ads and payouts. Each sync stores the ledger as one row per shop and UTC day, the same daily figures the Alura app's financial reports use. The API adds up those days and never calls Etsy.

* **Grain.** UTC days. A week starts on Monday.
* **Units and reviews** come from your orders and reviews, stored on the same daily rows.
* **Signs.** The ledger books costs as negative amounts. The API turns them around: every cost, fee and refund is a positive number.
* **Money** is plain numbers in `currency`, rounded to 2 decimals. Shares are fractions with 4 decimals.

## The default values

| Group | Value | Definition |
| - | - | - |
| `sales` | `revenue` | Sales booked to the payment account, after refunds and the taxes Etsy collects. |
| | `orders` | Orders, from the ledger. |
| | `units` | Items sold. |
| | `average_order_value` | Gross sales (`revenue_detail.gross_sales`) divided by `orders`. |
| | `refunds` | The amount refunded. |
| | `refund_count` | The number of refunds. |
| | `refund_rate` | `refund_count` divided by `orders`. |
| `costs` | `total` | Etsy's costs in the ledger (`fees.etsy_costs`), plus your own costs when you entered them. |
| | `etsy_fees` | Etsy's fees. |
| | `marketing` | Marketing: ads, Etsy Plus and Pattern. |
| | `seller_services` | Seller services: shipping labels bought on Etsy. |
| `profit` | `net` | `revenue` minus `costs.total`. |
| | `margin` | `net` divided by `revenue`. |
| `reviews` | `count` | Reviews written in the range. |
| | `average` | The average rating of those reviews, weighted by how many there were each day. |
| | `rate` | `count` divided by `units`. |

A share is `null` when what it divides by is `0` or unknown. It's never `0` for that reason.

## More detail with `expand`

`expand=` (on MCP, `include`) adds groups. Together they cover all 41 metrics of the Alura app's financial reports.

| Expansion | Values |
| - | - |
| `revenue_detail` | `gross_sales`, and the `sales_tax` and `sales_vat` Etsy collected from buyers |
| `fees` | `transaction`, `listing`, `payments_and_deposit` (payment processing and deposit fees, as one value), `etsy_costs` (all of Etsy's costs) and `your_costs` |
| `marketing` | `ad_spend`, `etsy_ads`, `offsite_ads`, `etsy_plus` and `pattern` |
| `seller_services` | `shipping_labels` |
| `ratios` | `fee_share`, `marketing_share`, `seller_services_share`, `cost_share` and `etsy_cost_share` (each divided by `revenue`), `etsy_profit` (revenue minus Etsy's costs), `etsy_margin`, and `items_per_order` |
| `balance` | `payments_to_etsy`, `payments_from_etsy` and `closing`, the payment account's balance at the end of the range |

**Adding up.** Money and counts are summed over the days. Shares are worked out again from the sums, never averaged across days. `closing` is the last day's balance, not a sum. Across several shops, everything is summed, closing balances included.

## Your own costs

Costs you enter in Alura (the Costs page) are your own costs, such as materials. They count only on days that have ledger data.

* **When you entered costs**, `fees.your_costs` holds them, and they're included in `costs.total` and `profit.net`.
* **When you didn't**, `fees.your_costs` is `null`, `costs.total` and `profit.net` hold Etsy's costs only, and a `your_costs_missing` notice names the shops. `profit.net_before_your_costs` then gives revenue minus Etsy's costs.

A shop counts as having entered costs if it ever has. With several shops, a shop without costs adds nothing to `your_costs`, and `your_costs_missing` names it.

## Currency

The ledger is in the payment account's currency. That can differ from the currency your listings show: some shops price in US dollars and are paid in another currency.

* **Per shop**, Alura reads the ledger's currency from its entries. When it can't tell, the currency is unknown.
* **The default `currency`** is the shops' common currency. When the shops use different currencies, it's US dollars. Ask for another with `currency=`; a code Alura has no exchange rate for is `422 unprocessable`.
* **Converting.** When anything was converted, the response has `conversion` (`from`, `to`, `rate_date`, `method: "current_rate"`) and a `currency_converted_at_current_rate` notice. History is converted at the rates of `rate_date`, not each day's rate. `conversion` is `null` when nothing was converted. Counts are never converted.
* **An unknown currency.** A single shop with an unknown currency gets `currency: null`. Mixed with other shops, its money can't be added up, so the call fails with `422 unprocessable`. Ask for that shop alone with `shop_id`, or add `group_by=shop`. With `group_by=shop`, the totals leave that shop out, `by_shop` shows it with `currency: null`, and a `currency_unknown` notice names it.

## Ranges, intervals and comparing

* **Range.** `period` is `7d`, `30d` (the default), `90d` or `365d`, ending on the last day covered for every included shop. Or give `from` and `to`, both included.
* **`interval`** is `day`, `week`, `month`, `quarter` or `year`, at most 366 points, and adds `series`.
* **`compare=previous_period`** adds `compare`, the same values for the period of the same length just before, and `change`: for each value, (this period minus the previous) divided by the absolute value of the previous, so a loss that shrinks from −100 to −50 reads `+0.5`. `change` is `null` when either value is unknown or the previous is `0`.
* **`group_by=shop`** adds `by_shop`, each shop's own values in the response currency.
* **Over MCP** (`get_my_shop_stats`), so an answer stays within an AI client's budget: at most 18 `series` points, `group_by=shop` over at most 16 shops (pass `shop_id` for more), and not `interval` and `group_by` together. A call past a limit is a `400 invalid_request` that suggests a coarser interval or a shorter range. REST keeps the 366 points and every shop.

## Missing days are never 0

Each shop has a coverage window in `coverage`: `from` is its first day with ledger data, and `through` is the day before the latest sync that stored both its ledger and its daily figures. A day Alura doesn't know is left out of the totals, and a notice names it. It's never counted as a day with no sales.

| Notice | When |
| - | - |
| `partial_range` | Part of the range, or of the compare period, is outside a shop's coverage. `missing` lists the days, per shop. |
| `no_financials_row` | A day inside coverage has no stored ledger data. Alura can't tell a quiet day from one it didn't store, so the day is unknown. |
| `metric_unavailable` | A metric's stored value is missing on some days. `missing` lists the days and `metrics` the values affected, which are `null`. |
| `stale_shops` | A shop's stats are more than 7 days old. |

A point of `series` with no data at all is `null` in every value. `closing` is `null` when the last day of its range or point has no data.

## Known limits

* **Quiet days look unknown.** A day with no ledger entries has no row, so a shop with few sales shows `null` days and `no_financials_row` notices.
* **Some days may hold zeros.** Until a fix to Alura's ledger sync (late 2026), a failed ledger read could still store a day's figures, with zeros for the entries it missed. Alura can't tell those zeros from real ones, so stats serve them as data. The fix stops new ones.

## Why listing revenue won't match

The revenue here won't equal the sum of your listings' `period` revenue for the same days, because the two come from different sources. Listing numbers come from orders: item price minus item discounts, in the orders' currency, on the day each order was placed, with refunds kept apart. Shop stats revenue comes from the payment ledger: after refunds and the taxes Etsy collects, in the payment account's currency, on the ledger's own dates. Each also has its own coverage. See [Listing stats](/methodology/listing-stats).

## Version history

| Version | Change |
| - | - |
| 2026-10 | First published version. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.