# Birthday sats

What was mined on a day: per row counts for the site's birthday page, and the mint-day table behind every date filter.

## Counts per day

`GET /api/birthday/counts`

Per row, how many tracked sats were mined on a UTC day (`date`), or on that month-day of every year (`md`, optionally only `years`), that the index locates. Cacheable 30 s; a cold day can take a few seconds.

#### Query parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `date` | string | no | A day, `YYYY-MM-DD`. One of `date` and `md` is required. |
| `md` | string | no | A month-day, `MM-DD`: that day of every year. |
| `years` | string | no | With `md`: only these years, comma-separated. |

#### Example request

```bash title="cURL"
curl 'https://raresats.net/api/birthday/counts?date=2009-01-09'
```
```js title="JavaScript"
const response = await fetch('https://raresats.net/api/birthday/counts?date=2009-01-09');
const data = await response.json();
```
```python title="Python"
import requests

data = requests.get("https://raresats.net/api/birthday/counts", params={"date": "2009-01-09"}).json()
```

#### Response `200`

| Field | Type | Description |
| --- | --- | --- |
| `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). |
| `days` | array of object | Each day counted (one for `date`; that day of every year for `md`). |
| `days[].date` | string | The day, YYYY-MM-DD. |
| `days[].from` | integer | Its first block. |
| `days[].to` | integer | Its last block. |
| `days[].rows` | map of integer | Tracked sats mined that day the index locates, per row (rows with none absent). |
| `rows` | map of integer | The days' counts summed per row. |
| `ms` | integer | Server time spent, ms. |

```json title="Response"
{
  "filter": {"years": [], "date": "2009-01-09", "md": null, "luck": null, "sub": null},
  "days": [
    {
      "date": "2009-01-09",
      "from": 470,
      "to": 559,
      "rows": {"vintage_alpha": 3, "vintage_omega": 1}
    }
  ],
  "rows": {"vintage_alpha": 3, "vintage_omega": 1},
  "ms": 749
}
```

#### Errors

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

| Status | When |
| --- | --- |
| 400 | Neither `date` nor `md`, or a malformed one. |
| 503 | Mint dates are still being read (`retry: true`), or the index is unavailable. |

## The mint-day table

`GET /api/days`

Which UTC day mined each block, compactly: what the site uses to date sats in the browser. A sat's mint day is the day of its block. Cacheable 30 s.

#### Example request

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

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

#### Response `200`

| Field | Type | Description |
| --- | --- | --- |
| `ready` | boolean | Whether the table is read (date filters answer 503 until then). |
| `version` | integer | Format version. |
| `genesis` | string \| null | The genesis block hash. |
| `first_day` | integer | The first UTC day (days since 1970) of the table. |
| `height` | integer | The last height covered. |
| `hash` | string \| null | Its hash. |
| `starts` | array of integer | Each day's first height, as deltas: `starts[0]` is the first day's, then each the difference from the day before. |
| `exceptions` | array of integer | Blocks whose time is out of order, as flat pairs `[height, day, …]`: the day each belongs to. |
| `tail` | array of integer | Recent, not yet final headers as flat pairs `[height, time, …]`. |
| `build_ms` | integer \| null | How long the last build took. |

#### Errors

None of its own.

Decoding it: day `first_day + i` (UTC days since 1970) starts at height `starts[0] + … + starts[i]`; a block listed in `exceptions` belongs to the day given there instead (its timestamp is out of order).
