# AlgorandTracker x402 Data API (English)

Paid Algorand / ASA / RWA (Exodus, WTR, ebitts, Meld) / USDC analytics over **HTTP 402** + **MainNet USDC**.  
Most routes use historical snapshots; `wallet-assets` is a live portfolio and Exodus `price-history` is USD.  
WTR and ebitts prices are estimated; Meld token prices are Vestige USDC (not metal spot). Website UI stays free. This document is for agents and developers calling `/x402`.

| | |
|--|--|
| Base URL | `https://algorandtracker.com` |
| Index (free) | `GET /x402` — JSON links to health, docs, examples |
| Health (free) | `GET /x402/health` — probes Tracker `/api` + facilitator **reachability**; **503** if a check fails. Facilitator probe treats any non-5xx HTTP response (including **404**) as reachable — it does not validate facilitator business APIs. |
| Docs (free) | `GET /x402/docs` (this document) |
| llms.txt (free) | `GET /llms.txt` — curated agent-readable product links |
| Origin discovery (free) | `GET /.well-known/x402` (also `/.well-known/x402.json`) |
| MCP | `https://algorandtracker.com/x402/mcp` — Streamable HTTP. Free: `get_docs`. Paid subset (MainNet USDC): `get_algo_activity`, `get_algo_top_holders`, `get_activity_highlights`, `get_algo_nodes`, `get_asa_monthly_report`. Activity/highlights MCP tools are **daily only**. **Full catalog is HTTP `/x402/*`, not MCP.** |
| Facilitator | GoPlausible (`https://facilitator.goplausible.xyz`) |
| Network | Algorand MainNet |
| Asset | USDC ASA `31566704` |
| Challenge tag | `x402-global-challenge` |
| Discovery | [Bazaar resources](https://facilitator.goplausible.xyz/discovery/resources?q=algorandtracker) |
| Product type | **Composite** (many endpoints, one `payTo`) |
| Official X account | [@AlgoAsaTrack](https://x.com/AlgoAsaTrack) |

---

## How payment works

x402 v2 uses these HTTP headers (canonical names):

| Header | Direction | Role |
|--------|-----------|------|
| `PAYMENT-REQUIRED` | Response (402) | Base64 challenge (amount, asset, `payTo`, network, extensions) |
| `PAYMENT-SIGNATURE` | Request (retry) | Client payment proof for the quoted requirement |
| `PAYMENT-RESPONSE` | Response (success) | Settlement / receipt after a successful paid call |

Browser clients calling from another origin need CORS `Access-Control-Expose-Headers`
to include `PAYMENT-REQUIRED` and `PAYMENT-RESPONSE` (this gateway exposes them on `/x402/*`).
The same `Access-Control-Allow-Origin: *` CORS applies to `/llms.txt`, `/.well-known/x402`,
and `/.well-known/x402.json`.

**SDK / middleware order** (not “settle, then retry”):

1. Call a paid `GET` **without** payment → **HTTP 402** + `PAYMENT-REQUIRED`.
2. Client builds and signs the payment, then **retries the same URL** with `PAYMENT-SIGNATURE`.
3. Gateway **verifies** the proof with the facilitator.
4. If verification succeeds, the **handler** runs (proxies Tracker `/api`).
5. If the handler returns success (HTTP status below 400), the gateway **settles** on-chain and returns **HTTP 200** + JSON + `PAYMENT-RESPONSE`.
6. If the handler returns HTTP 400 or higher after a verified proof, settlement is **not** completed for that attempt.

Use an x402-compatible client (e.g. `@x402/fetch` + `@x402/avm`).  
One payment = one successful response (for paged lists: **one page**).

---

## Tracked assets (`asaId`)

Use numeric `asaId` in `/x402/asa/{asaId}/...` paths (digits only).

| asaId | Asset | Notes |
|------:|-------|--------|
| `0` | ALGO (native) | Top holders, activity, wallet-history, supply, monthly. Also use `/x402/algo/*` for nodes & foundation. **No** `app-unique-senders`. |
| `393537671` | ASA.STATS | Top-holders cap **200** |
| `700965019` | Vestige (VEST) | `appName=Vestige` |
| `1138500612` | GORA | Stake/validators under `/x402/gora/*`; `appName=GoraStake` |
| `3160000000` | HAY | Stake under `/x402/hay/*`; `appName=Haystack` |
| `2200000000` | TINY | Tinyman stake under `/x402/tinyman/*`; top-holders cap **700**; `appName=Tinyman` |
| `3203964481` | Folks | `appName=FolksFinance` |
| `2726252423` | Alpha Arcade | `appName=AlphaArcade` |
| `1284444444` | Orange | No `app-unique-senders` |
| `2994233666` | POWER | `appName=PactFi` |

Default top-holders list size for other ASAs: **500**. ALGO: **2000** wallets above ~**100k ALGO**.

Paid `/x402/asa/{asaId}/...` routes enforce the live first-party Tracker catalog before payment.
Unknown/untracked IDs return **400**; if the catalog is unavailable or too old they return **503**.
Neither case requests payment.
EXIT, WTR, ebitts plant ids, Meld GOLD$/SILVER$, and USDC are **blocked on `/x402/asa/{asaId}`** even if they later appear in `Assets`.

**Exodus EXIT** (`asaId` `213345970`) is an RWA token, **not** in `Assets` / this table.
Do **not** call `/x402/asa/213345970/...` (400). Use `/x402/rwa/exodus/...`.

**Wateract WTR** (`asaId` `1675316597`) is RWA, **not** in `Assets`.
Do **not** call `/x402/asa/1675316597/...` (400). Use `/x402/rwa/wtr/...`.
No left-list / new-to-list / price-history routes.

**ebitts** (`asaId` `3543829261` Barile Venosa / `3543834155` Piani della Marina) is RWA, **not** in `Assets`.
Do **not** call `/x402/asa/{those ids}/...` (400). Use `/x402/rwa/ebitts/{slug}/...` with `slug` `bven` or `pdm`.
No left-list / new-to-list / price-history routes.

**Meld** (`asaId` `246516580` GOLD$ / `246519683` SILVER$) is RWA, **not** in `Assets`.
Do **not** call `/x402/asa/{those ids}/...` (400). Use `/x402/rwa/meld/{slug}/...` with `slug` `gold` or `silver`.
Circulating is grams (1 token = 1 gram of vaulted metal) and excludes the official reserve. Price is Vestige USDC, not metal spot. The ASA mint cap is unused and is not circulating.
No left-list / new-to-list / price-history routes.

**Circle USDC** (`asaId` `31566704`) is a stablecoin, **not** RWA and **not** in `Assets`.
It is also the x402 payment ASA. Do **not** call `/x402/asa/31566704/...` (400). Use `/x402/stablecoins/usdc/...`.
No left-list / new-to-list / price-history routes.

**Lofty** is not in the paid catalog.

---

## Common query rules

| Query | Allowed | Defaults / errors |
|-------|---------|-------------------|
| `period` | `daily` \| `weekly` \| `monthly` | HTTP activity, activity-supply-distribution, highlights. Omit → **daily**. Invalid → **400**. Case-insensitive |
| `days` | Lookback: `7` \| `30` \| `60` \| `90` \| `180`. Price-history: `1` \| `7` \| `30` \| `60` | Lookback: invalid/missing → priced as **30**. Price-history (`/price-history` only): omit → **7**; other values → **400**. Not a calendar date |
| `maxDays` | `30` \| `90` \| `180` | Omit → full available history (**$0.10**). Other values → **400**. On ALGO `nodes-history`, `nodes-stake-share`, `nodes-bucket-history`, `nodes-wallet-history`, `foundation-total-history`, and Exodus/WTR/ebitts/Meld/USDC `daily-history`, omit is proxied as `maxDays=366` (Tracker `/api` omit defaults to 90 or 180, which would under-deliver vs the $0.10 tier) |
| `page` | integer ≥ 0 | List routes only. Default **0**. One payment = one page |
| `pageSize` | Route-specific (below) | Invalid/unsupported → **400** before payment |
| `sortBy` | Route-specific (below) | Unsupported fields/routes → **400** before payment |
| `order` | `asc` \| `desc` | List routes only; case-insensitive |
| `walletPrefix` | string | Optional on top-holders, LP, nodes, Foundation, GORA/HAY/Tinyman, WTR, ebitts, Meld, and USDC wallet lists |
| `walletAddress` | 58-character Algorand address | Required on `*-wallet-history`; invalid format → **400** before payment. `wallet-assets` uses the same checksum rule in the **path** |
| `validatorAddress` | 58-character Algorand address | Required on `gora/validator-stake-history` and `gora/validator-details` |
| `recordDate` | `YYYY-MM-DD` | Activity and activity-supply-distribution: weekly/monthly only. Highlights: weekly only. Daily always returns latest. **Required** on `monthly-report` |
| `appName` | See list below | Required on `app-unique-senders` (not an ASA id) |
| `bucketKey` | See list below | Required on `algo/nodes-bucket-history` |

### Paged list parameters

| Route | `pageSize` | `sortBy` | Other |
|-------|------------|----------|-------|
| `asa/{asaId}/top-holders`, `rwa/exodus/top-holders`, `rwa/wtr/top-holders`, `rwa/ebitts/{slug}/top-holders`, `rwa/meld/{slug}/top-holders`, `stablecoins/usdc/top-holders` | `10` \| `15` \| `25` \| `50` \| `100` (default `15`) | `Amount` \| `TotalAmount` \| `DailyChange` \| `WeeklyChange` \| `MonthlyChange` \| `Change90` \| `Change180` | `walletPrefix`, `order` |
| `algo/nodes` | integer `1–100` (default `15`) | `Amount` \| `DailyChange` \| `WeeklyChange` \| `MonthlyChange` \| `Change90` \| `Change180` \| `UpgradeVote` | `walletPrefix`, `order` |
| `gora/stake-wallets` | integer `1–200` (default `100`) | `TotalStake` \| `DailyChange` \| `WeeklyChange` \| `MonthlyChange` \| `Change90` \| `Change180` | `walletPrefix`, `order` |
| `gora/validators` | integer `1–200` (default `100`) | Same GORA sort fields | `order`; no `walletPrefix` |
| `hay/stake` | integer `1–200` (default `100`) | `Amount` \| `DailyChange` \| `WeeklyChange` \| `MonthlyChange` \| `Change90` \| `Change180` (**no** `UpgradeVote`) | `walletPrefix`, `order` |
| `tinyman/stake` | integer `1–200` (default `100`) | `Amount` \| `DailyChange` \| `WeeklyChange` \| `MonthlyChange` \| `Change90` \| `Change180` (**no** `UpgradeVote`) | `walletPrefix`, `order` |

Internal presentation/tweet parameters (`metaOnly`, `includeLegends`, `forTweet`,
`includeScore1`) are not part of the paid product and return **400 before payment**.
Any query parameter that is not listed for that route (including typos such as
`foo=bar` or `peroid`) returns **400 before payment**. Known parameters such as
`days`, `maxDays`, paging, or sorting also return 400 when supplied to a route
that does not support them.

### `appName` values (`/x402/app-unique-senders`)

**Exact spelling and capitalization required** (verified live):

| `appName` | Related ASA |
|-----------|-------------|
| `Tinyman` | `2200000000` TINY |
| `Vestige` | `700965019` VEST |
| `FolksFinance` | `3203964481` Folks |
| `Haystack` | `3160000000` HAY |
| `GoraStake` | `1138500612` GORA |
| `PactFi` | `2994233666` POWER |
| `AlphaArcade` | `2726252423` Alpha |

- **ALGO (`asaId=0`) has no `appName`.** Do not use this endpoint for native ALGO.
- ASA.STATS (`393537671`) and Orange (`1284444444`) have no `appName`.
- Wrong case (e.g. `tinyman`) or unknown names (e.g. `ALGO`, `0`) return **400 before payment**.

### `bucketKey` values (`/x402/algo/nodes-bucket-history`)

**Exact keys** (all verified with data): `0-1k` · `1k-30k` · `30k-1m` · `1m-10m` · `10m+` · `total`  
Invalid key → **400 before payment**.

---

## Pricing rules

| Rule | Amounts |
|------|---------|
| Activity / activity-supply-distribution `period` | daily **$0.02** · weekly **$0.06** · monthly **$0.16** |
| Highlights `period` | daily **$0.05** · weekly **$0.15** · monthly **$0.40** |
| `days` lookback | 7→**$0.02** · 30→**$0.04** · 60→**$0.05** · 90→**$0.06** · 180→**$0.08** (invalid/missing → priced as 30) |
| Lookback **bulk** (`*-bulk`) | **$0.20** fixed — all five windows (7\|30\|60\|90\|180) in one response. Five separate ladder calls would be **$0.25**; bulk is ~**20%** less. No `days` query |
| `maxDays` history | 30→**$0.02** · 90→**$0.04** · 180→**$0.06** · omit→**$0.10** (other values → **400**). ALGO nodes/foundation history and Exodus/WTR/ebitts/Meld/USDC `daily-history` omit is proxied as `maxDays=366` so $0.10 is not under-delivered vs the free `/api` shorter omit default |
| ASA / Exodus price-history (`days` 1\|7\|30\|60) | **$0.03** |
| Snapshot + change cols (holders / LP / Gora / Hay) | **$0.08** |
| Tinyman stake (same change cols) / nodes / foundation / validators / validator-details | **$0.06** |
| Tracked assets catalog / RWA total / Exodus / WTR / ebitts / Meld / USDC summary | **$0.05** |
| Wallet assets (live portfolio) | **$0.10** |
| Supply distribution | **$0.03** |
| Supply distribution history | **$0.10** (full history; no `maxDays`) |
| Monthly-report months list | **$0.01** |
| Monthly report (full) | **$0.50** (required `recordDate`) |
| Full wallet/validator stake histories (no `maxDays` ladder) | **$0.10** |

These are the production catalog prices. Fixed-price routes can be overridden with
the documented `PRICE_*` environment variables; the amount in each live HTTP 402
payment requirement is authoritative.

---

## Verified examples

These URLs were checked against production. **Free** paths return **200**. **Paid** paths return **402** without payment (path/query OK). After a successful paid retry (verify → handler → settle) → **200** + JSON.

### Free (no payment)

```http
GET https://algorandtracker.com/x402
GET https://algorandtracker.com/x402/health
GET https://algorandtracker.com/x402/docs
```

### Paid — catalog / ALGO analytics

```http
GET https://algorandtracker.com/x402/tracked-assets
GET https://algorandtracker.com/x402/asa/0/activity?period=daily
GET https://algorandtracker.com/x402/asa/0/activity-supply-distribution?period=daily
GET https://algorandtracker.com/x402/asa/0/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/asa/0/top-holders-previously-bulk
GET https://algorandtracker.com/x402/asa/0/supply-distribution
GET https://algorandtracker.com/x402/asa/700965019/price-history?days=7
GET https://algorandtracker.com/x402/algo/nodes?page=0&pageSize=15
GET https://algorandtracker.com/x402/algo/nodes?page=0&pageSize=15&sortBy=UpgradeVote
GET https://algorandtracker.com/x402/algo/nodes-bucket-history?bucketKey=30k-1m&maxDays=30
GET https://algorandtracker.com/x402/algo/nodes-stake-share?maxDays=30
GET https://algorandtracker.com/x402/algo/foundation-holders
```

`top-holders` for ALGO: response includes `"totalCount":2000` and `"topHoldersDisplayLimit":2000`.

Wallet history (replace address with any wallet from top-holders):

```http
GET https://algorandtracker.com/x402/asa/0/wallet-history?walletAddress=N2C374IRX7HEX2YEQWJBTRSVRHRUV4ZSF76S54WV4COTHRUNYRCI47R3WU&maxDays=30
```

### Paid — ASA / apps / stake

```http
GET https://algorandtracker.com/x402/asa/700965019/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/app-unique-senders?appName=Tinyman&maxDays=30
GET https://algorandtracker.com/x402/app-unique-senders?appName=Vestige&maxDays=30
GET https://algorandtracker.com/x402/gora/stake-wallets?page=0&pageSize=15
GET https://algorandtracker.com/x402/gora/validator-details?validatorAddress=FKMRNDA3GDI337FLRBV6IMIORK32DQAMKYUJYH26JPD4HFWWVJURXWHSRE
GET https://algorandtracker.com/x402/hay/stake?page=0&pageSize=15
GET https://algorandtracker.com/x402/hay/stake-previously?days=30
GET https://algorandtracker.com/x402/hay/stake-new-entrants?days=30
GET https://algorandtracker.com/x402/tinyman/stake?page=0&pageSize=15
GET https://algorandtracker.com/x402/tinyman/stake?page=0&pageSize=15&sortBy=DailyChange
GET https://algorandtracker.com/x402/tinyman/stake-previously?days=30
GET https://algorandtracker.com/x402/tinyman/stake-new-entrants?days=30
GET https://algorandtracker.com/x402/activity-highlights?period=daily
GET https://algorandtracker.com/x402/rwa/exodus/summary
GET https://algorandtracker.com/x402/rwa/exodus/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/rwa/total
GET https://algorandtracker.com/x402/rwa/wtr/summary
GET https://algorandtracker.com/x402/rwa/wtr/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/rwa/ebitts/summary
GET https://algorandtracker.com/x402/rwa/ebitts/bven/summary
GET https://algorandtracker.com/x402/rwa/ebitts/pdm/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/rwa/meld/summary
GET https://algorandtracker.com/x402/rwa/meld/gold/summary
GET https://algorandtracker.com/x402/rwa/meld/silver/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/stablecoins/usdc/summary
GET https://algorandtracker.com/x402/stablecoins/usdc/top-holders?page=0&pageSize=15
GET https://algorandtracker.com/x402/wallet-assets/N2C374IRX7HEX2YEQWJBTRSVRHRUV4ZSF76S54WV4COTHRUNYRCI47R3WU
```

Monthly report: first call months (cheap), then full report with a `recordDate` from that list:

```http
GET https://algorandtracker.com/x402/asa/393537671/monthly-report/months
GET https://algorandtracker.com/x402/asa/393537671/monthly-report?recordDate=2026-07-31
```

(`recordDate` values change over time — always read from `/months` first. `2026-07-31` was valid when this doc was written.)

### Expected without payment

| Call | HTTP |
|------|------|
| Free paths above | **200** |
| Paid paths above | **402** + payment requirements |
| `GET .../activity?period=yearly` | **400** |
| `GET .../app-unique-senders` (no `appName`) | **400** |
| `GET .../nodes-bucket-history?bucketKey=foo` | **400** |
| `GET .../asa/0/price-history` | **400** |
| `GET .../asa/213345970/top-holders` | **400** (EXIT is RWA, not Assets) |
| `GET .../asa/1675316597/top-holders` | **400** (WTR is RWA, not Assets) |
| `GET .../asa/31566704/top-holders` | **400** (USDC is not Assets) |
| `GET .../rwa/ebitts/foo/summary` | **400** (slug must be `bven` or `pdm`) |
| `GET .../rwa/meld/platinum/summary` | **400** (slug must be `gold` or `silver`) |
| `GET .../asa/246516580/top-holders` | **400** (Meld GOLD$ is RWA, not Assets) |
| `GET .../asa/246519683/top-holders` | **400** (Meld SILVER$ is RWA, not Assets) |

---

## Endpoint catalog

### Free

| Method | Path | Notes |
|--------|------|--------|
| GET | `/x402` | Product index JSON (links, examples) |
| GET | `/x402/health` | Status + upstream/facilitator **reachability** probes (`checks`); facilitator non-5xx (e.g. 404) counts as ok; **503** when `ok` is false |
| GET | `/x402/docs` | This document (Markdown) |
| MCP (POST/GET) | `/x402/mcp` | Streamable HTTP transport; initialize/list are free, tool payment is tool-specific |

### Catalog

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/tracked-assets` | $0.05 | All tracked assets in one JSON: `asaId`, name, symbol, supply, ALGO price, 24h change, market caps. No query params. ALGO price/market-cap fields are null |

### ALGO / ASA core (`asaId` = `0` or tracked ASA)

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/asa/{asaId}/activity` | period ladder | `period`; `recordDate` only for weekly/monthly; daily is latest |
| GET | `/x402/asa/{asaId}/activity-supply-distribution` | period ladder | Activity-tab scored supply/price moves (not the snapshot `/supply-distribution`). `recordDate` only for weekly/monthly; daily is latest. Empty `metrics` = no qualifying moves |
| GET | `/x402/asa/{asaId}/top-holders` | $0.08 | Paged (`page`, `pageSize`, `sortBy`, `order`, `walletPrefix`). Caps: ALGO 2000 (>~100k); default ASA 500; ASA.STATS 200; TINY 700 |
| GET | `/x402/asa/{asaId}/top-holders-previously` | days ladder | Left latest list; peak in window; DEX/pool excluded |
| GET | `/x402/asa/{asaId}/top-holders-previously-bulk` | $0.20 | All windows `data["7"…"180"]`; no `days` |
| GET | `/x402/asa/{asaId}/top-holders-new-entrants` | days ladder | On latest list; first-seen in window; DEX/pool excluded |
| GET | `/x402/asa/{asaId}/top-holders-new-entrants-bulk` | $0.20 | All windows; no `days` |
| GET | `/x402/asa/{asaId}/wallet-history` | maxDays ladder | required `walletAddress` |
| GET | `/x402/asa/{asaId}/price-history` | $0.03 | `days` `1`\|`7`\|`30`\|`60` (omit=7). **Not** ALGO `asaId=0` |

### ALGO nodes & foundation

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/algo/nodes` | $0.06 | Paged (`page`, `pageSize`, route-specific `sortBy` including `UpgradeVote`, `order`, `walletPrefix`); amount, change cols, incentive / key end / sig type / `upgradeVote` |
| GET | `/x402/algo/nodes-history` | maxDays ladder | Aggregate history |
| GET | `/x402/algo/nodes-stake-share` | maxDays ladder | Community vs Foundation **online-node ALGO** share (`WalletNames.Type=AlgorandFoundation`). Latest percents + daily rows. Not Foundation tab balances (`foundation-total-history`) |
| GET | `/x402/algo/nodes-bucket-history` | maxDays ladder | required `bucketKey` (`0-1k` … `10m+` \| `total`) |
| GET | `/x402/algo/nodes-wallet-history` | maxDays ladder | required `walletAddress` |
| GET | `/x402/algo/nodes-previously` | days ladder | Not on latest online-node day; amount in window |
| GET | `/x402/algo/nodes-previously-bulk` | $0.20 | All windows; no `days` |
| GET | `/x402/algo/nodes-new-entrants` | days ladder | On latest list; first amount day in window |
| GET | `/x402/algo/nodes-new-entrants-bulk` | $0.20 | All windows; no `days` |
| GET | `/x402/algo/foundation-holders` | $0.06 | Full list (not paged); amount + change columns; optional `walletPrefix` |
| GET | `/x402/algo/foundation-total-history` | maxDays ladder | |

### ASA LP / supply / monthly

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/asa/{asaId}/pool-lp` | $0.08 | Up to **300** LP wallets; full response (not paged); change columns; optional `walletPrefix` |
| GET | `/x402/asa/{asaId}/pool-lp-previously` | days ladder | DEX pool wallets left latest LP list; peak LP in window |
| GET | `/x402/asa/{asaId}/pool-lp-previously-bulk` | $0.20 | All windows; no `days` |
| GET | `/x402/asa/{asaId}/pool-lp-wallet-history` | maxDays ladder | required `walletAddress` |
| GET | `/x402/asa/{asaId}/supply-distribution` | $0.03 | Current categories / institutions snapshot |
| GET | `/x402/asa/{asaId}/supply-distribution-history` | $0.10 | Full history; no `maxDays` |
| GET | `/x402/asa/{asaId}/monthly-report/months` | $0.01 | Available months |
| GET | `/x402/asa/{asaId}/monthly-report` | $0.50 | required `recordDate` |

### Apps / stake / highlights

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/app-unique-senders` | maxDays ladder | required `appName` (see list; **not** ALGO) |
| GET | `/x402/gora/stake-wallets` | $0.08 | GORA (`1138500612`); paged with GORA sort fields; change cols through 180 days |
| GET | `/x402/gora/stake-wallets-previously` | days ladder | Latest-day stake 0; stake in window |
| GET | `/x402/gora/validators` | $0.06 | Paged with GORA sort fields; no `walletPrefix` |
| GET | `/x402/gora/validator-details` | $0.06 | required `validatorAddress`; name, live validator balance, staking wallets |
| GET | `/x402/gora/wallet-stake-history` | $0.10 | required `walletAddress`; full history (no `maxDays`) |
| GET | `/x402/gora/validator-stake-history` | $0.10 | required `validatorAddress`; full history |
| GET | `/x402/hay/stake` | $0.08 | HAY (`3160000000`); paged with amount/change sort fields; change cols through 180 days |
| GET | `/x402/hay/stake-previously` | days ladder | Latest-day stake 0; stake in window |
| GET | `/x402/hay/stake-new-entrants` | days ladder | On latest list (Amount >= 10); first stake day in window |
| GET | `/x402/hay/wallet-stake-history` | $0.10 | required `walletAddress`; full history |
| GET | `/x402/tinyman/stake` | $0.06 | TINY (`2200000000`); paged with amount/change sort fields; change cols through 180 days (**no** `UpgradeVote`) |
| GET | `/x402/tinyman/stake-previously` | days ladder | Latest-day stake 0; stake in window |
| GET | `/x402/tinyman/stake-new-entrants` | days ladder | On latest list (Amount >= 10); first stake day in window |
| GET | `/x402/tinyman/wallet-stake-history` | $0.10 | required `walletAddress`; full history |
| GET | `/x402/activity-highlights` | highlights period ladder | `period`; `recordDate` only for weekly; daily/monthly are latest |

### Exodus RWA / wallet

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/rwa/exodus/summary` | $0.05 | EXIT (`213345970`) circulating, holders, EXOD USD price, market caps. No query |
| GET | `/x402/rwa/exodus/daily-history` | maxDays ladder | Daily circulating / on-chain mcap / USD price. Omit → proxied as 366 |
| GET | `/x402/rwa/exodus/price-history` | $0.03 | `days` `1`\|`7`\|`30`\|`60` (omit=7). Points use `priceUsd` |
| GET | `/x402/rwa/exodus/top-holders` | $0.08 | Top 300; same paging/sort as ASA top-holders |
| GET | `/x402/rwa/exodus/wallet-history` | maxDays ladder | required `walletAddress` |
| GET | `/x402/rwa/exodus/top-holders-previously-bulk` | $0.20 | All windows; no `days` |
| GET | `/x402/rwa/exodus/top-holders-new-entrants-bulk` | $0.20 | All windows; no `days` |
| GET | `/x402/wallet-assets/{address}` | $0.10 | Live portfolio (ALGO, ASA, stake, pools, NFTs). Path address checksum required. May be `partial`/`truncated`. Upstream 429 is not settled |

### RWA total / WTR / ebitts / Meld

No left-list, new-to-list, or `price-history` on these routes. Lofty is not listed.

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/rwa/total` | $0.05 | Homepage RWA heading total: Exodus + WTR + ebitts + Meld Gold/Silver on-chain mcap USD. Not Lofty, not USDC. WTR/ebitts prices estimated; Meld Vestige USDC. No query |
| GET | `/x402/rwa/wtr/summary` | $0.05 | WTR (`1675316597`); estimated BitMart **$3.20**, not a live feed. No query |
| GET | `/x402/rwa/wtr/daily-history` | maxDays ladder | Daily circulating / on-chain mcap / estimated USD price. Omit → proxied as 366 |
| GET | `/x402/rwa/wtr/top-holders` | $0.08 | Cap **200**; three company wallets excluded; same paging/sort as ASA top-holders |
| GET | `/x402/rwa/wtr/wallet-history` | maxDays ladder | required `walletAddress` |
| GET | `/x402/rwa/ebitts/summary` | $0.05 | Both plants. Estimated EUR→USD (`/ 0.86`). No query |
| GET | `/x402/rwa/ebitts/{slug}/summary` | $0.05 | `slug` `bven` (`3543829261`) or `pdm` (`3543834155`). Other slugs → **400** |
| GET | `/x402/rwa/ebitts/{slug}/daily-history` | maxDays ladder | Same slug rule. Omit → proxied as 366 |
| GET | `/x402/rwa/ebitts/{slug}/top-holders` | $0.08 | Cap **400**; official reserve + inventory excluded; same paging/sort |
| GET | `/x402/rwa/ebitts/{slug}/wallet-history` | maxDays ladder | required `walletAddress` |
| GET | `/x402/rwa/meld/summary` | $0.05 | GOLD$ (`246516580`) + SILVER$ (`246519683`). Vestige USDC, not metal spot. Circulating grams; official reserve excluded. No query |
| GET | `/x402/rwa/meld/{slug}/summary` | $0.05 | `slug` `gold` or `silver`. Other slugs → **400**. Do not call `/x402/asa/{asaId}` |
| GET | `/x402/rwa/meld/{slug}/daily-history` | maxDays ladder | Same slug rule. Omit → proxied as 366. No `price-history` route |
| GET | `/x402/rwa/meld/{slug}/top-holders` | $0.08 | Cap **200**; official reserve excluded; same paging/sort |
| GET | `/x402/rwa/meld/{slug}/wallet-history` | maxDays ladder | required `walletAddress` |

### USDC (stablecoin, not RWA)

| Method | Path | Price | Notes |
|--------|------|------:|--------|
| GET | `/x402/stablecoins/usdc/summary` | $0.05 | USDC (`31566704`) circulating / on-chain mcap. No query |
| GET | `/x402/stablecoins/usdc/daily-history` | maxDays ladder | Daily circulating / on-chain mcap. Omit → proxied as 366 |
| GET | `/x402/stablecoins/usdc/top-holders` | $0.08 | Cap **200**; two reserve wallets excluded; same paging/sort as ASA top-holders |
| GET | `/x402/stablecoins/usdc/wallet-history` | maxDays ladder | required `walletAddress` |

---

## HTTP errors

| HTTP | Meaning |
|------|---------|
| 402 | Payment required (or payment simulation/settle failed) |
| 400 | Invalid/missing query (bad `period`, `maxDays`, `asaId`, `bucketKey`, missing `walletAddress` / `appName` / `recordDate`, etc.) |
| 404 | Resource data or `DOCS.md` was not found |
| 429 | Nginx request limit exceeded, or Tracker `/api/wallet-assets` rate limit (not settled) |
| 500 | An upstream Tracker API internal error was passed through |
| 502 | Upstream Tracker API is unreachable |
| 503 | Tracker data/service unavailable, or MCP handler not ready during startup |
| 504 | Upstream Tracker API exceeded `UPSTREAM_TIMEOUT_MS` (default **30 seconds**) |
| 200 | Paid success; JSON body |

Error JSON messages are in **English**.
Other upstream 4xx/5xx status codes are passed through. MCP tool failures are returned
as MCP/JSON-RPC tool errors rather than these HTTP data-route responses.

Gateway HTTP upstream calls time out after `UPSTREAM_TIMEOUT_MS` (default **30 seconds**).
Nginx allows **90 seconds** for HTTP `/x402` data routes and **120 seconds** for MCP streaming/tool calls.

---

## Agent demo scenarios (copy-paste)

Use with an **x402-capable** client that can pay MainNet USDC (not a normal chat MCP
connection alone). Flow: unpaid GET → HTTP 402 + `PAYMENT-REQUIRED` → retry with
`PAYMENT-SIGNATURE` → verify → handler → settle → JSON + `PAYMENT-RESPONSE`.

| If the user/agent asks… | Pay this URL (one request) |
|-------------------------|----------------------------|
| Which assets does AlgorandTracker track, with supply and price? | `GET https://algorandtracker.com/x402/tracked-assets` (**$0.05**) |
| Show ALGO top holders, first page | `GET https://algorandtracker.com/x402/asa/0/top-holders?page=0&pageSize=15` (**$0.08**) |
| Daily ALGO activity for the latest snapshot | `GET https://algorandtracker.com/x402/asa/0/activity?period=daily` (**$0.02**) |
| Chart of who left ALGO top holders across 7/30/60/90/180 days | `GET https://algorandtracker.com/x402/asa/0/top-holders-previously-bulk` (**$0.20**) |
| Current online ALGO nodes, first page (includes totals + amount buckets) | `GET https://algorandtracker.com/x402/algo/nodes?page=0&pageSize=15` (**$0.06**) |
| Community vs Foundation share of online-node ALGO (30d) | `GET https://algorandtracker.com/x402/algo/nodes-stake-share?maxDays=30` (**$0.02**) |
| Tinyman unique senders, last 30 days | `GET https://algorandtracker.com/x402/app-unique-senders?appName=Tinyman&maxDays=30` (**$0.02**) |
| Vestige 7-day price in ALGO | `GET https://algorandtracker.com/x402/asa/700965019/price-history?days=7` (**$0.03**) |
| Exodus EXIT summary | `GET https://algorandtracker.com/x402/rwa/exodus/summary` (**$0.05**) |
| Homepage RWA on-chain total (Exodus+WTR+ebitts+Meld) | `GET https://algorandtracker.com/x402/rwa/total` (**$0.05**) |
| Wateract WTR summary | `GET https://algorandtracker.com/x402/rwa/wtr/summary` (**$0.05**) |
| Meld Gold summary | `GET https://algorandtracker.com/x402/rwa/meld/gold/summary` (**$0.05**) |
| Circle USDC summary | `GET https://algorandtracker.com/x402/stablecoins/usdc/summary` (**$0.05**) |
| Wallet holdings for one address | `GET https://algorandtracker.com/x402/wallet-assets/N2C374IRX7HEX2YEQWJBTRSVRHRUV4ZSF76S54WV4COTHRUNYRCI47R3WU` (**$0.10**) |

Example prompt you can paste into an x402 agent:

```text
Pay MainNet USDC via x402 and GET https://algorandtracker.com/x402/asa/0/top-holders?page=0&pageSize=15
Then summarize the top 5 wallets by amount.
```

Full catalog and prices: this document. Free index: `GET /x402`.

---

## Discovery for agents

1. Open `GET https://algorandtracker.com/x402` (free index).  
2. Read `/llms.txt`, `/.well-known/x402`, or this document at `/x402/docs`.  
3. Search Bazaar for `algorandtracker` or browse facilitator discovery.  
4. Pay with MainNet USDC and call the listed HTTPS URL.  
5. Optional: MCP at `https://algorandtracker.com/x402/mcp` for a **small paid tool subset**; use HTTP for the full catalog.

The website footer includes a single English link **Paid API (x402)** → `/x402/docs` for
human discovery. Analytics pages and `/api` behavior are otherwise unchanged.

HTTP 402 challenges include provider metadata: service name, topical tags, and the
public `https://algorandtracker.com/logo.png` icon. Social discovery points to the
official [@AlgoAsaTrack](https://x.com/AlgoAsaTrack) account.

The five paid MCP tools are a deliberately small, **daily-only** subset and include separate
Bazaar metadata (`type=mcp`) in their payment requirements and payloads. MCP resources are
uniquely identified by the MCP URL plus tool name.

Current facilitator note (verified 2026-08-07): GoPlausible discovery returned HTTP records
but no MCP records globally, even though the paid MCP payload contained both the canonical
resource URL and Bazaar metadata and settled successfully. Direct MCP usage at `/x402/mcp`
works; `type=mcp` indexing depends on facilitator support being enabled.

### Route templates vs Bazaar records

- The gateway defines **72 paid HTTP route templates**.
- Bazaar stores concrete settled resources, so ASA ids and query variants can produce
  many more records than 72.
- Origin discovery surfaces restate this: `GET /x402`, `/llms.txt`, and
  `/.well-known/x402` expose flagship examples plus the catalog/Bazaar distinction;
  they are not a second full menu.
- Old localhost or earlier query records may remain visible in dashboard history; active
  production resources use `https://algorandtracker.com/x402/...`.
- MCP tool records are separate from HTTP records even though they share `/x402/mcp`.

### MCP transport configuration

```json
{
  "mcpServers": {
    "algorandtracker-x402": {
      "url": "https://algorandtracker.com/x402/mcp"
    }
  }
}
```

**Browser / Origin:** If the request includes an `Origin` header, it must equal
`PUBLIC_ORIGIN` (production: `https://algorandtracker.com`). Any other `Origin` →
**HTTP 403**. Requests with **no** `Origin` (typical server / non-browser clients) are allowed.

Standard Cursor/Claude MCP clients can connect and use `get_docs`, but they do **not**
automatically pay MainNet USDC. Paid tools require an x402-capable MCP client and wallet.

---

## What this is not

- Not a replacement for the free website or free `/api` used by the UI.  
- `/x402` is the **paid** machine/agent surface.  
- No API keys; payment is per request via x402.  
- No A2A Agent Card is published because this service does not implement the A2A
  JSON-RPC task protocol. Discovery is x402 index + llms.txt + origin manifest +
  Bazaar + MCP.
