# Network API

Public, read-only JSON for everything on the MLX ledger: blocks, transactions, accounts, seats, the curve, compute rewards and the Macs on the map. No key, CORS open.

## Base URL

```text
https://mlx.app/api
```

The same routes answer on `https://explorer.mlx.app/api` (one deployment serves both hosts). Every page on [explorer.mlx.app](https://explorer.mlx.app) is built from these endpoints, so anything you see there you can read here.

```endpoint try
GET /api/stats
```

```bash tab=curl
curl https://mlx.app/api/stats
```

```js tab=JavaScript
const res = await fetch("https://mlx.app/api/stats");
const { chain, head } = await res.json();
console.log(chain, head.height);
```

```python tab=Python
import requests

d = requests.get("https://mlx.app/api/stats").json()
print(d["chain"], d["head"]["height"])
```

## The basics

- **JSON in, JSON out.** Every endpoint returns `application/json`, except the CSV of [compute rewards](/network/compute) and the [open data](/network/open-data) files.
- **No key for reads.** Nothing on this section needs an account, a token or a signature. Writing to the ledger is a signed `POST /api/tx`, covered in [Submitting transactions](/transactions/submitting).
- **CORS is open.** Every `/api/*` response carries `Access-Control-Allow-Origin: *`, with `GET, POST, OPTIONS` allowed and `content-type` as the only allowed request header, so you can call the API straight from a page on any site.
- **Only GET.** Every route on these pages is a `GET`. A route that doesn't exist answers with the site's HTML 404 page, not JSON.

## Amounts

Ledger amounts are **strings of base units**, never floats. Every token on the ledger (MLX, USDC and the legacy USDT) has 6 decimals:

| Field value | Means |
| --- | --- |
| `"1000000"` | 1 MLX (or 1 USDC) |
| `"250000000"` | 250 USDC |
| `"491755419"` | 491.755419 MLX |

Read them as big integers (`BigInt` in JavaScript, `int` in Python) and divide by 10^6 only to display them.

A few summary fields are plain numbers in whole units instead, because they are prices or derived figures, not balances. Each page says which. The main ones:

- [`/api/token`](/network/stats#token) gives prices, supply and holders in whole MLX and dollars.
- [`/api/curve`](/network/market) gives prices in dollars per MLX and history points in whole MLX.
- `units` and `position` (the network's place on the curve) are counted in seat units, and can carry floating-point noise such as `27.020000000000003`.

## Times

Every timestamp is **milliseconds since the Unix epoch, UTC** (`ts`, `receivedAt`, `created`, `until`, `seen`, `at`). Hours (`hour` on a compute reward) and days are the millisecond value of the start of that UTC hour or day.

## Caching

Each route sets its own `Cache-Control`, and Vercel's CDN may serve a copy that is a few seconds old:

| Kind of data | Cache-Control |
| --- | --- |
| Live lists and totals (blocks, transactions, seats, accounts, the curve, World) | `public` with a short `max-age` and `stale-while-revalidate` |
| One sealed block (`/api/block/<height>`) | `public, immutable`: a sealed block never changes |
| Things that must be exact right now (`/api/stats`, `/api/account/<name>`, live mining, quotes, errors) | `no-store` |
| Open data files | `public` with a long `max-age`; the URL always serves the newest version |

The response headers are the source of truth; read them rather than hard-coding a refresh rate. Rate limits on reads: see [Rate limits](/resources/rate-limits).

## Names and privacy

- Wallet names end in `.mlx` (`luca.mlx`). Protocol accounts are named the same way: `treasury.mlx`, `compute.mlx`, `rewards.mlx`, `community.mlx`, `team.mlx`, `bridge.mlx`, `withdrawals.mlx`.
- What people buy is a **dedicated seat**. The API keeps the older word in its ids and paths: `/api/nodes`, `/api/node/<id>`, `nodes` fields and the `buy_node` transaction all mean seats.
- A Mac's own name is never published. Public reads show the kind of Mac ("MacBook Pro") instead. See [Transactions](/network/transactions#mac-names).

## Errors

An error is a JSON object with one field, `error`, and an HTTP status:

```json
{ "error": "Block not found" }
```

The statuses each route uses are listed on [Errors](/resources/errors).

## Endpoints

:::cards
- [Stats and supply](/network/stats) The chain head, network totals, the allocation and the token page's figures.
- [Blocks](/network/blocks) Signed, hash-linked blocks, and how to check a block yourself.
- [Transactions](/network/transactions) Recent and filtered transactions, and one transaction by hash.
- [Accounts](/network/accounts) Balances, locks, linked Macs, history, live mining, names and keys.
- [Seats](/network/seats) Every dedicated seat, filtered and sorted.
- [Market](/network/market) The curve, its history and spot buy and sell quotes.
- [Compute](/network/compute) Every compute reward, reconciled, and the network's work in numbers.
- [World](/network/world) The Macs on the map and the network's output over the last day.
- [Open data](/network/open-data) Macs, models and what runs where, as versioned JSON and CSV.
- [Errors](/resources/errors) The error format and every status code.
- [Rate limits](/resources/rate-limits) What is limited, and how.
:::
