# Sales stats

## Every row's market

`GET /api/sales/stats`

Per row: the last unit price, the 30-day median unit price, volume and sales, and all-time sales. With `years`, `month` or `luck`, every row's market over only the sales of its sats of those years, that month or those lucks (matched as `/api/sales` matches them; the sales' outlier verdicts are their row's), and `filter` echoed: the Statistics' sales columns under a year, month or luck filter, and a collection's head under its Activity filter. Confirmed sales only: pending (mempool) sales never count.

#### Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `years` | string | no | Only the sales of each row's sats mined in these years (comma-separated YYYY, 2009 to this year; `year` too). |
| `month` | string | no | Only the sales of each row's sats mined in this month (UTC, `YYYY-MM`, by each block's own time), matched on the dashboard: any rare-sat index. |
| `blocks` | string | no | Only the sales of each row's sats mined in these blocks: heights `from-to`, inclusive (`1000-5000`), or one block (`9`), up to the tip (400 past it or for a malformed or reversed range), matched on the dashboard: any rare-sat index. |
| `luck` | string | no | Only the sales of each row's sats mined in blocks of these lucks: `N` (N or more) or `N-M`. |

#### Example request

```bash title="cURL"
curl 'https://raresats.net/api/sales/stats?years=2009&month=2017-12&blocks=1000-5000&luck=10'
```
```js title="JavaScript"
const response = await fetch('https://raresats.net/api/sales/stats?years=2009&month=2017-12&blocks=1000-5000&luck=10');
const data = await response.json();
```
```python title="Python"
import requests

data = requests.get("https://raresats.net/api/sales/stats", params={"years": "2009", "month": "2017-12", "blocks": "1000-5000", "luck": "10"}).json()
```

#### Response `200`

| Field | Type | Description |
| --- | --- | --- |
| `available` | boolean | Whether the sales index is available. |
| `generation` | integer | Sales generation. |
| `seq` | integer | The newest sale's sequence number. |
| `count` | integer | Sales held. |
| `as_of` | object \| null | `{height, time}`. |
| `first_time` | integer \| null | The first sale, unix seconds. |
| `stats` | map of object | Per row. |
| `stats.<key>.last_unit_price` | number \| null | The last sale's unit price (outliers excluded). |
| `stats.<key>.last_time` | integer \| null | Its time. |
| `stats.<key>.median_30d` | number \| null | 30-day median unit price. |
| `stats.<key>.volume_30d` | integer | 30-day volume in sats. |
| `stats.<key>.volume_all` | integer | All-time volume in sats (inscribed sales aside). |
| `stats.<key>.sales_30d` | integer | 30-day sales. |
| `stats.<key>.sales` | integer | Sales in all. |

#### Errors

`{error}` (a message, no code):

| Status | When |
| --- | --- |
| 400 | A malformed `years`, `month` or `luck`. |
| 429 | Too many new filtered answers (each a pass over every sale) from your network (an IPv4 address or IPv6 /64), or from everyone at once: `retry: true`; try again after `Retry-After` seconds. Answers already built are served all the same. |
| 501 | `years` or `luck` asked of a server without the sat filters. |
| 503 | The mint days or the block luck are still being read (`retry: true`), or the luck is not available. |

With `?years=2009`, `?month=2017-12`, `?blocks=1000-5000` or `?luck=10` (or several), every row's market is over only the sales of its own sats mined in those years, in that month, in those blocks (heights, inclusive), or in blocks of those lucks: a sale counts under its row when a sat of that row it sold passes, as the collection's Activity filters it (`/api/sales/query?row=…&years=…`). The sales keep their row's outlier verdicts.

## A sale's transaction

`GET /api/sales/{seq}/tx`

A 302 redirect to the sale's transaction page, `/tx/{txid}` (the compact sales carry only part of the txid). With `accept: application/json`, `{txid, href}` instead.

#### Path parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `seq` | integer | yes | The sale's sequence number. (min 0) |

#### Example request

```bash title="cURL"
curl 'https://raresats.net/api/sales/1/tx'
```
```js title="JavaScript"
const response = await fetch('https://raresats.net/api/sales/1/tx');
const data = await response.json();
```
```python title="Python"
import requests

data = requests.get("https://raresats.net/api/sales/1/tx").json()
```

#### Response `200`

| Field | Type | Description |
| --- | --- | --- |
| `txid` | string |  |
| `href` | string | `/tx/{txid}`. |

```json title="Response"
{
  "txid": "d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2",
  "href": "/tx/d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2"
}
```

#### Response `302`

Redirect; `location` is `/tx/{txid}`.

#### Errors

`{error}` (a message, no code):

| Status | When |
| --- | --- |
| 404 | No such sale. |

To turn sats into dollars at the time of a sale, use the daily BTC/USD history of [Prices](https://raresats.net/docs/get-prices.md).

Stats are of confirmed sales only: a sale still in the mempool (`pending` in [Sales](https://raresats.net/docs/get-sales.md)) never counts.
