> ## Documentation Index
> Fetch the complete documentation index at: https://docs.windrose.market/llms.txt
> Use this file to discover all available pages before exploring further.

# API overview

> Public GraphQL and HTTP endpoints for launches, trades, candles, holders, currencies, vaults and FX rates on every chain Windrose runs on.

<Frame className="wr-art">
  <img src="https://mintcdn.com/windrose/G2X0jK9uSBPQAS-b/images/art/api.webp?fit=max&auto=format&n=G2X0jK9uSBPQAS-b&q=85&s=f1b763e962e315d9dac15415b2554a3e" alt="A spool of paper tape unrolling across stone" width="1600" height="686" data-path="images/art/api.webp" />
</Frame>

Everything the Windrose app shows off-chain comes from one indexer per chain, and the same endpoints are open to you. There are no API keys and no sign-up: the endpoints are public and best-effort.

## Endpoints

One indexer runs per chain. Each serves the same GraphQL API over the chain's own data.

| Chain             | Chain id | Base URL                              |
| ----------------- | -------- | ------------------------------------- |
| Robinhood Chain   | 4663     | `https://api.windrose.market`         |
| Robinhood testnet | 46630    | `https://api.windrose.market/testnet` |
| Arc testnet       | 5042002  | `https://api-arc.windrose.market`     |

The Robinhood testnet indexer sits behind a path prefix on the mainnet host, so its routes are `/testnet/graphql`, `/testnet/status` and so on.

Every indexer answers these routes:

| Route           | What it returns                                                                                                |
| --------------- | -------------------------------------------------------------------------------------------------------------- |
| `POST /graphql` | The GraphQL API. Opening `/` or `/graphql` in a browser loads GraphiQL with the schema.                        |
| `/sql/*`        | SQL over HTTP for [`@ponder/client`](https://ponder.sh/docs/query/client), a typed client for the same tables. |
| `GET /health`   | `200` as soon as the process is up.                                                                            |
| `GET /ready`    | `200` once historical indexing is complete, `503` while the backfill is still running.                         |
| `GET /status`   | The latest indexed block per chain.                                                                            |
| `GET /metrics`  | Prometheus metrics.                                                                                            |

The web app also exposes two JSON routes of its own on `https://windrose.market`: `/api/chains` lists every registered chain and whether it is deployed, and `/api/deployment?chainId=<id>` returns the contract addresses for a chain. They are documented with the other [HTTP endpoints](/api/graphql#http-endpoints) generated from the OpenAPI file.

All responses carry `access-control-allow-origin: *`, so a browser can query the indexer directly from any origin.

## First request

The plural query for launches, newest first, with the fields the launch cards use:

<CodeGroup>
  ```bash curl theme={"system"}
  curl -s https://api.windrose.market/graphql \
    -H 'content-type: application/json' \
    -d '{"query":"{ launchs(orderBy: \"createdAt\", orderDirection: \"desc\", limit: 5) { items { token symbol currency lastPriceQuote lastPriceUsd volumeQuote holderCount graduated } } }"}'
  ```

  ```javascript fetch theme={"system"}
  const res = await fetch("https://api.windrose.market/graphql", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      query: `query Launches($limit: Int) {
        launchs(orderBy: "createdAt", orderDirection: "desc", limit: $limit) {
          items { token symbol currency lastPriceQuote lastPriceUsd volumeQuote holderCount graduated }
          pageInfo { hasNextPage endCursor }
        }
      }`,
      variables: { limit: 5 },
    }),
  });
  const { data, errors } = await res.json();
  if (errors) throw new Error(errors.map((e) => e.message).join("; "));
  console.log(data.launchs.items);
  ```
</CodeGroup>

Every `bigint` column arrives as a decimal string. Prices are 1e18 fixed point and amounts are 18-decimal "quote units", so divide before you display anything. The [GraphQL conventions](/api/graphql) page covers pagination, filters and units; the query pages cover one table each.

<Columns cols={2}>
  <Card title="GraphQL conventions" icon="braces" href="/api/graphql">
    Query shape, filters, cursors, units and the semantics that trip people up.
  </Card>

  <Card title="Launches" icon="rocket" href="/api/queries/launches">
    One row per launch: curve state, price, volume, holders, graduation.
  </Card>

  <Card title="Trades" icon="arrow-left-right" href="/api/queries/trades">
    Curve buys and sells, plus pool swaps where they are indexed.
  </Card>

  <Card title="Candles" icon="chart-candlestick" href="/api/queries/candles">
    1-minute and 1-hour OHLC in the launch currency.
  </Card>

  <Card title="Holders" icon="users" href="/api/queries/holders">
    Current balances per launch, or one wallet across launches.
  </Card>

  <Card title="Currencies" icon="coins" href="/api/queries/currencies">
    Registry state per currency with the latest oracle rate.
  </Card>

  <Card title="Vaults" icon="vault" href="/api/queries/vaults">
    Collateral snapshots and mint, redeem, deposit and withdraw events.
  </Card>

  <Card title="Rates" icon="trending-up" href="/api/queries/rates">
    Every rate the keeper oracle has posted.
  </Card>
</Columns>

## How the data is produced

The indexer is a [Ponder](https://ponder.sh) app (`packages/indexer` in the repository). It reads the deployment file for its chain and follows these contracts from the deployment block:

| Source                                                                 | Events                                                                                   | Tables written                                  |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------- |
| `LaunchFactory`                                                        | `LaunchCreated`, `LaunchMetadata`                                                        | `launch`, `curve`                               |
| `BondingCurve` (one clone per launch, discovered from `LaunchCreated`) | `Buy`, `Sell`, `ReadyToGraduate`, `Graduated`, `CreatorFeesClaimed`, `ProtocolFeesSwept` | `trade`, `candle`, `launch`, `pool`, `feeClaim` |
| `LaunchToken` (one per launch)                                         | `Transfer`                                                                               | `holder`, `launch.holderCount`                  |
| `FxVault` (one per Windrose currency)                                  | `Minted`, `Redeemed`, `Deposited`, `Withdrawn`, `Donated`                                | `vaultEvent`, `vaultSnapshot`                   |
| `KeeperFxOracle`                                                       | `RatePosted`                                                                             | `rate`, `currency.lastRate`                     |
| `CurrencyRegistry`                                                     | `CurrencySet`                                                                            | `currency`                                      |
| Uniswap v4 `PoolManager`                                               | `Swap`, only for pools of graduated launches                                             | `trade`, `candle`, `launch.lastPrice*`          |

Pool swaps are the one source that differs per chain. On Robinhood Chain the launchpad uses the official Uniswap v4 `PoolManager`, which emits every swap on the chain, so the mainnet indexer runs with `INDEX_POOL_SWAPS=false` and does not follow it. Post-graduation trades on Robinhood Chain are therefore not in `trades` or `candles`, and `launch.lastPriceQuote` stops at the graduation price; the app reads the live pool price from `StateView` instead. Robinhood testnet and Arc testnet deploy their own `PoolManager`, so their indexers do record swaps.

<Note>
  Handlers read contract state at the event's block (curve parameters at creation, `vault.status()` at every vault event), so each indexer needs an archive RPC. That is why the public testnet RPCs are not enough to run one yourself; see [Indexer](/operate/indexer).
</Note>

## Chains and addresses

The chain id decides which base URL you talk to, and the [addresses page](/protocol/addresses) lists the contracts each indexer follows. `GET https://windrose.market/api/chains` returns the same list at runtime, including the indexer URL the app uses per chain.
