inu

Reference · v1

Read every square's live state as JSON.

The whole board is public. No key, no account, no rate card — just GET it. Build a bot that watches for cheap listings, a screensaver that renders the mosaic, a bridge that mirrors the ledger somewhere else. None of it needs our permission.

Conventions

base
All endpoints live under /api/v1. Responses are JSON; errors are { "error": string } with a real status code.
money
Every amount is lamports, as a decimal string. Never a JSON number — a price can exceed Number.MAX_SAFE_INTEGER and parsing it as a float silently loses money. Divide by 1e9 for SOL, carefully.
cors
Access-Control-Allow-Origin: * on every read endpoint. Call it straight from a browser.
rate limit
120 requests per minute per IP. The remaining budget comes back in X-RateLimit-Remaining. Over it you get a 429 and no hard feelings.
caching
Read endpoints are edge-cached for a few seconds. A revealed tile is immutable — its pixels never change, only its owner does.

Endpoints

get/api/v1/mosaic

The board in one object: its shape, how much is revealed, what the next piece costs, and the ids of every revealed square.

{
  "grid": { "cols": 40, "rows": 25, "total": 1000 },
  "revealed": 0,
  "unclaimed": 1000,
  "holders": 0,
  "nextPriceLamports": "20000000",
  "volumeLamports": "0",
  "market": { "listings": 0, "offers": 0, "swaps": 0 },
  "revealedPieceIds": [],
  "image": "/api/mosaic"
}

get/api/v1/pieces

All 1000 squares in id order.

?claimed=true or ?claimed=false to filter. ?limit= and ?offset= to page.
{
  "total": 1000,
  "count": 1000,
  "offset": 0,
  "pieces": [
    {
      "id": 0,
      "label": "0000",
      "col": 0,
      "row": 0,
      "claimed": false,
      "owner": null,
      "pieceNumber": null,
      "mintPriceLamports": null,
      "acquiredAt": null,
      "tile": null
    }
  ]
}

get/api/v1/pieces/:id

One square, with its open listing, its offer book, and any swaps proposed for it.

{
  "id": 512,
  "label": "0512",
  "col": 32,
  "row": 12,
  "claimed": true,
  "owner": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  "pieceNumber": 3,
  "mintPriceLamports": "20000000",
  "acquiredAt": "2026-08-28T01:14:02.881Z",
  "tile": "/api/tile/512",
  "listing": null,
  "offers": [],
  "swapsOffered": [],
  "events": "/api/v1/pieces/512/events"
}

get/api/v1/pieces/:id/events

Everything that has ever happened to one square, newest first. Cursor through with the returned nextBefore.

?limit= up to 200, ?before= an event id.
{
  "pieceId": 512,
  "count": 1,
  "nextBefore": null,
  "events": [
    {
      "id": "1",
      "pieceId": 512,
      "kind": "mint",
      "from": null,
      "to": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
      "priceLamports": "20000000",
      "signature": "4Nd1mB…",
      "at": "2026-08-28T01:14:02.881Z"
    }
  ]
}

get/api/v1/market

The whole book: open listings, live offers and proposed swaps.

{
  "listings": [],
  "offers": [],
  "swaps": [],
  "note": "Offers are not escrowed. An accepted offer is an invitation to pay, not a claim on funds."
}

get/api/v1/events

The board's whole history across every piece, newest first.

?limit=
{ "count": 0, "events": [] }

get/api/v1/wallets/:address

What one wallet holds, what it has bid on, and what swaps it is party to.

{
  "wallet": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  "piece": { "id": 512, "col": 32, "row": 12, "pieceNumber": 3,
             "mintPrice": "20000000", "acquiredAt": "2026-08-28T01:14:02.881Z" },
  "offers": [],
  "swaps": []
}

Images

Two routes return pixels rather than JSON, and both are gated on the ledger rather than on a key.

/api/mosaic
The board as one WebP, 1600×1000, with every unclaimed square punched out to transparent. On an empty board it is a completely transparent image, which is the correct answer.
/api/tile/:id
One 100 × 100 square. Returns 404 if nobody owns it — that is the reveal mechanic, not an error to work around.

Writing

There is no public write API and there will not be one, because every write is authorised by a wallet signature that only a wallet can produce. Buying goes /api/reserve SystemProgram.transfer/api/claim; listings, offers and swaps are signed messages posted to /api/market/*. The message text is rebuilt server-side from the fields you send, so a signature cannot be moved onto a different action than the one your wallet showed you.

Try itGET /api/v1/mosaic The live board, right now, as JSON.BackgroundHow this works The mechanism, the price curve, and what is and is not on chain.

Ownership is a database row, not a token — read the honest section before you build anything that depends on it.