# Query sales

`GET /api/sales/query`

Sales on every marketplace, newest first, filtered by row, rarer sub-category, mint years, a mint month, a mint day or a month-day (birthday sats), and sat luck; with facets. Page with `before` = the previous answer's `next`. Cacheable 30 s.

#### Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `row` | string | no | Only this row (collection). None: every row. |
| `sub` | string | no | A rarer sub-category of `row` (e.g. `pizza_uncommon` under `uncommon`): only items holding sats of it. Implies `subs=1`. |
| `subs` | string | no | `1` includes the row's sub-category items (sold or listed under their own rows). One of: `0`, `1`. Default: `0`. |
| `led` | string | no | With `row`: `1` adds the sales led by another row that sold sats of it (every other row a sale sold sats of is one of its secondary rows), each with `led: true`. A collection's Activity asks `subs=1&led=1`: every sale that sold a sat of the row. One of: `0`, `1`. Default: `0`. |
| `years` | string | no | Mint years, comma-separated (`2009,2010`; up to 40): items holding a sat mined in one of them. Each must be a year sats were mined in, 2009 to this one (400 otherwise); repeats and order do not matter. `year` is accepted too. |
| `month` | string | no | A mint month, `YYYY-MM` (UTC, by each block's own time): items holding a sat mined that month. Combines with the other filters. |
| `blocks` | string | no | A block range: heights `from-to`, inclusive (`1000-5000`), or one block (`9`): items holding a sat mined in those blocks. Up to the tip (400 past it or for a malformed or reversed range). Combines with the other filters. |
| `date` | string | no | A mint day, `YYYY-MM-DD` (UTC), 2009 to this year: items holding a sat mined that day. Exclusive with `md`. |
| `md` | string | no | A month-day, `MM-DD`: items holding a sat mined that day of any year (with `years`, of those years). Birthday sats. |
| `luck` | string | no | Sat luck, a minimum (`8`: luck 8 or more) or an inclusive range (`8-12`), 0 to 254: items holding a sat of that luck. A sat's luck is its block's: the leading zero bits of the block hash less those of the block's target. Combines with the other filters (the matched sat passes them all). 503 for the few seconds after a first start while the luck of every block is read. |
| `limit` | integer | no | Page size, 1-200. Default: `50`. (min 1, max 200) |
| `before` | integer | no | A sequence number: only older sales (the previous page's `next`). (min 1) |

#### Example request

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

data = requests.get("https://raresats.net/api/sales/query", params={"row": "uncommon", "years": "2009", "month": "2017-12", "blocks": "1000-5000", "luck": "8", "limit": 2}).json()
```

#### Response `200`

| Field | Type | Description |
| --- | --- | --- |
| `available` | boolean | Whether the sales index is available. |
| `generation` | integer | Sales generation (a reorg starts a new one). |
| `seq` | integer | The newest sale's sequence number. |
| `as_of` | object \| null | `{height, time}` of the sales. |
| `row` | string \| null | The row asked for. |
| `filter` | object | The filter as the server understood it. |
| `filter.years` | array of integer | The years asked for (ascending), `[]` for none. |
| `filter.month` | string \| null | The month asked for (`YYYY-MM`), `null` for none. |
| `filter.date` | string \| null | The day asked for. |
| `filter.md` | string \| null | The month-day asked for. |
| `filter.blocks` | object \| null | The blocks asked for: `{from, to}`, heights inclusive (one block: `from` = `to`), `null` for none. |
| `filter.blocks.from` | integer |  |
| `filter.blocks.to` | integer |  |
| `filter.luck` | object \| null | The luck asked for: `{min, max}` (`max` `null` for a minimum alone), `null` for none. |
| `filter.luck.min` | integer |  |
| `filter.luck.max` | integer \| null |  |
| `filter.sub` | string \| null | The sub-category asked for. |
| `filter.subs` | boolean | Whether sub-category items are included (absent on events and counts). |
| `filter.led` | boolean | Whether sales led by another row are included (`led=1`; sales only). |
| `total` | integer | Matching sales (all pages). |
| `kinds` | object | Of `total`, how the sales are under `row`: `own` (its own sales, the only ones in its stats and line), `sub` (a rarer sub-category's, with `subs=1`) and `led` (led by another row, with `led=1`). Without `row`, every sale is `own`. |
| `kinds.own` | integer |  |
| `kinds.sub` | integer |  |
| `kinds.led` | integer |  |
| `facets` | object | Counts for refining the filter. |
| `facets.years` | map of integer | Matching items per mint year (each item counted once per year it holds). |
| `facets.luck` | map of integer | Luck minimums: `{N: items holding a sat of luck N or more}` from N = 1 up to the highest, counting the filter but its `luck` (what `luck=N` would match). `{}` while the luck table is being read. |
| `facets.subs` | array of object | The row's sub-categories, in the index's order (`[]` without a row). |
| `facets.subs[].row` | string | A sub-category row. |
| `facets.subs[].count` | integer | Matching items holding it. |
| `facets.rows` | map of integer | Without `row`: matching items per own row. |
| `facets.types` | object | `/api/sales/query` with a `row` only: the row's sales that pass the filter (its sub-categories' sales too, whatever `subs` says; never those another row led) by kind, the set of exact type combinations each sold. A plain uncommon, an alpha uncommon and an alpha uncommon sold with a black omega are three kinds: the rarer ones show what skews the row's prices. |
| `facets.types.kinds` | array of object | The 12 commonest kinds, by sales, most first. |
| `facets.types.kinds[].types` | array of array of string | The type combinations its sales sold, each in the badges' order, the lead row's first (`[["uncommon", "alpha"], ["black", "omega"]]`). `[]` for sales the fork typed none of. |
| `facets.types.kinds[].row` | string | The own row of its first sale counted: a sub-category of `row` (the `sub` that filters to it) or `row` itself. |
| `facets.types.kinds[].count` | integer | Its sales. |
| `facets.types.kinds[].priced` | integer | Those the median is of: inscribed, outlier and free sales aside. |
| `facets.types.kinds[].median` | number \| null | Their median unit price per sat of `row`, to the hundredth of a sat; `null` with none priced. |
| `facets.types.other` | object |  |
| `facets.types.other.kinds` | integer | Kinds not listed. |
| `facets.types.other.count` | integer | Their sales. |
| `sales` | array of object | One page, newest first. |
| `sales[].seq` | integer | The sale's sequence number. |
| `sales[].time` | integer | Unix seconds. |
| `sales[].height` | integer | Block height. |
| `sales[].row` | string | The row it is shown as (its own, or one it is a sub-category of or a secondary row of). |
| `sales[].own` | string | Its own row. |
| `sales[].sub` | boolean | A sub-category sale shown under `row`. |
| `sales[].led` | boolean | A sale led by another row, shown under `row`, one of its secondary rows (with `led=1`). |
| `sales[].secondary` | map of integer | A sale's secondary rows: the market rows of the other sats it sold (not its own row, a row it is a sub-category of, or a label row), each with its sats, primary-first: `{"black_omega": 1}` for a black omega sold with an alpha uncommon; `{}` for none. A sale never counts in its secondary rows' markets (the primary-sat rule, in Concepts). |
| `sales[].types` | array of [TypeGroup](https://raresats.net/docs/listing-object.md) | The sats it sold grouped by exact type combination: the group of its own row's sat first, then rarest first (an alpha uncommon sold with a black omega: `uncommon, alpha` then `black, omega`). A piece longer than one sat (a block 9 chunk) counts under its first sat's types. `[]` when the fork typed none. |
| `sales[].unit` | number \| null | Unit price per sat of `row`. |
| `sales[].count` | integer | Sats of `row` sold. |
| `sales[].price` | integer \| null | Price in sats. |
| `sales[].sats` | integer | Tracked sats sold. |
| `sales[].sat` | integer \| null | The first special sat sold. |
| `sales[].sat_height` | integer \| null | The block that mined it. |
| `sales[].mined` | string \| null | Its mint day, YYYY-MM-DD. |
| `sales[].match` | object \| null | The sat that made the item pass a date or luck filter: its number, block, mint day (UTC) and luck. `null` without such a filter. |
| `sales[].match.sat` | integer | The sat. |
| `sales[].match.height` | integer | The block that mined it. |
| `sales[].match.date` | string \| null | Its mint day, YYYY-MM-DD. |
| `sales[].match.luck` | integer \| null | Its luck (its block's: the leading zero bits of the block hash less the target's); `null` while the luck table is being read. |
| `sales[].market` | string | Marketplace id. |
| `sales[].tx` | string \| null | The txid's first 8 and last 4 hex digits (`/api/sales/{seq}/tx` redirects). |
| `sales[].inscribed` | boolean | An inscription was on a sold sat. |
| `sales[].outlier` | boolean | A statistical outlier. |
| `sales[].seller` | string \| null | The seller's address. |
| `sales[].buyer` | string \| null | The buyer's address. |
| `next` | integer \| null | Pass as `before` for the next page; `null` on the last. |
| `ms` | integer | Server time spent, ms. |

#### Errors

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

| Status | When |
| --- | --- |
| 400 | A malformed parameter (e.g. a `date` that is no date, `date` with `md`). |
| 404 | An unknown `row` or `sub`. A retired row (`uncommon_2009`, `rare_2009`) answers 404 too, its `retired` field naming the row and years to ask for instead. |
| 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. |
| 503 | Mint dates or sat luck are still being read (`retry: true`): try again in a few seconds. Without `retry`: this server has no sat luck for its chain. |

Each sale names its secondary rows (`secondary`: every other row it sold sats of, with the fork's count of each); with `row` and `led=1` the answer also lists the sales led by another row that sold sats of it (`led: true`), and with `subs=1` its rarer sub-categories' (`sub: true`). `kinds` counts the sales by which of these they are; only `own` sales are in the row's stats. A collection's Activity asks `subs=1&led=1`: every sale that sold a sat of the row.

Each sale also names the exact types of the sats it sold (`types`, grouped by type combination, its own row's sat first), so an alpha uncommon or a pizza uncommon among a row's sales is told from a plain one. With a `row`, `facets.types` breaks the row's sales down by kind (the set of type combinations each sold) with each kind's sales and median unit price: the rarer kinds are what lift a row's prices. A kind's `row` is the sub-category (`sub`) that filters to it.

How the filters combine, and examples: [Filtering & birthday sats](https://raresats.net/docs/guide-filters.md). For every sale of a row as compact columns, unfiltered, use [Sales](https://raresats.net/docs/get-sales.md).
