DEVELOPERS / READ API

Read API

Everything this site shows comes from an indexer we run: a Cloudflare Worker that reads Robinhood Chain and keeps the result in a database. The same endpoints our pages call are open to you — no key, no sign-up, CORS open to any origin. They are a convenience, not an authority: every number below can be re-derived from the contracts, and when the indexer is wrong or down, the chain is still right.

Base URL

https://api.artificialgatointelligence.com/api

All responses are JSON with ok: true on success and { "ok": false, "error": "..." } with a 4xx or 5xx status otherwise. Every endpoint is GET. Amounts are returned in the quote asset, not in dollars: prices in dollars are a presentation layer of this site, built from the rates in /api/stats.

Endpoints

GET /api/stats
Protocol totals, the last 30 days of volume and launches, top tokens and creators, and the USD rate of each quote asset under prices. This is the only place the dollar rates come from.
GET /api/launches
The launch list. ?limit= 1-200 (default 50), ?offset=, ?sort= newest | progress | volume | holders | trending (24 h volume in dollars). Each token carries its price, phase, progress, supply, pool reserves (pool_token_f, pool_quote_f), its live holders count and its last 24 h (trades24h, volume24hQuote, volume24hUsd, change24hPct).
GET /api/coin/:token
One token: the same object as above plus holders, stats24h and supplyBreakdown, the supply split described under Trust — liquidity, burned, creator, protocol and market, with the top-10 concentration measured on the market share alone. stats24h also splits the day into buys / sells, buy_volume_quote / sell_volume_quote and distinct buyers / sellers.
GET /api/trades
The latest trades across every launch, newest first, with the token's symbol and pair already joined. ?limit= 1-60 (default 20).
GET /api/trades/:token
The trades of one token. ?limit= 1-200 (default 50). Curve trades and pool trades both appear; the curve field is null for the ones that happened in the Uniswap pool.
GET /api/candles/:token
OHLC candles. ?res= 1m | 5m | 15m | 1h, ?limit= 1-1000 (default 200). There is no daily resolution: build it by grouping hourly candles, which is what this site does.
GET /api/holders/:token
Holders by balance. ?limit= 1-500 (default 100), ?offset=. Read the tag field before drawing conclusions: an address may be the pool, the curve, the locker, the hook, the burn address or the creator. The largest "holder" of a graduated token is normally the pool, and calling that a whale is the most common mistake made about this data.
GET /api/wallet/:address
What one address holds across the launches we index, valued at each token’s live price. Each position carries a cost object — avg, paid, bought, sold, received, pnl, pnlPct, since — built from the buys and sells this indexer recorded, in the asset the token is paired with. It is null when there are no indexed buys: tokens that arrived by transfer have no cost, and reporting zero would say they were free.
GET /api/traders
The wallets holding the most across the launches we index, in dollars so pairs can be compared. ?window=24h | 7d | 30d answers a different question over a different table: how much each wallet moved in that window (bought, sold, traded), and it carries no profit figure — measuring profit backwards needs what a position was worth when the window opened, which we do not have. Without a window it is the all-time table below. Each carries paid, received, value, pnl, pnlPct, trades, the stack of tokens it trades (tokens, up to six { token, symbol }, and tokensTotal) and a tag when the address is the pool, the curve, the escrow or a creator. ?limit= 1-50 (default 10), ?sort=value (default) or paid. Read movedOut first: when a wallet bought and then moved the tokens to another address without selling, pnl is null, because those tokens still exist somewhere this indexer cannot follow and calling that a total loss would be wrong.
GET /api/burns/:token
Every burn of that token — a Transfer to 0x…dEaD — newest first, with amountF, the running total cumulativeF, pctOfSupply and the transaction hash. ?limit= 1-500 (default 100) caps the rows returned; total, totalCount and totalPct always describe every burn, not just the page. Without a token the endpoint lists recent burns across tokens and total, totalCount and every row’s cumulativeF are null — adding up burns of different tokens would be adding different units.
GET /api/profile/:address
How a wallet chooses to show up: an optional name, a color from a fixed palette (with its colorHex), an optional one-line bio, an X handle (x, stored bare, plus the xUrl we build from it — we never store a URL somebody else could point anywhere) and, if it uploaded one, pfpUrl. A wallet that never set anything still gets a deterministic color (isDefaultColor: true), so every address renders the same on the site, in the bot and in cards. GET /api/profiles?addresses=a,b,c returns up to 100 at once.
GET /api/thesis/:token
What holders say about a token. Each entry carries the text, the timestamp and price it was posted at, balanceThen, balanceNow (0 if the author sold since; null if unknown), likes and the author profile. A thesis whose author no longer holds is closed, with the author’s last sale as closePrice and the move since posting as closedPct. Newest first, or ?sort=likes; ?viewer=0x… adds likedByViewer; ?limit= 1-200 (default 50), ?offset=.
GET /api/holders/:token/pnl?addresses=a,b,c
Up to 100 holders of one token at once: each one’s balance, first-seen since, buys, sells, paid, received, avgEntry (null without indexed buys, as in /api/wallet) and its thesis on that token, if any. It is what the holders table of a coin page reads.
GET /api/trader/:address
One wallet as a trader: trades, firstSeen, lastSeen, avgHoldSeconds, openPositions, its bestTrades in dollars (pnlUsd, pnlPct, avgEntryMcUsd, open, movedOut), its badges (creator, graduate, burner, diamond, early), its theses, mostLikedThesis and launches. Built from the per-wallet aggregates the indexer maintains, so it never rescans the trade log.
GET /api/follows/:address
Who a wallet follows (following, followingCount) and how many follow it (followers). Follows are public and signed, like everything else a wallet writes here.
GET /api/crews · GET /api/crew/:id
Crews: a name and a list of wallets, with no admin and no invitations — you join and leave by signing, the same way you follow someone. The list carries each crew’s memberCount; ?member=0x… answers which crew one wallet is in (null for none). One wallet belongs to at most one crew, so that “this wallet’s crew” always has an answer.
GET /api/search?q=
Two characters or more: tokens by symbol, name or address and traders by profile name or address. Hidden tokens never appear, the same filter the hub applies.
GET /api/feed
The launchpad as a timeline: trades, thesis, launches and burns as one list of events, newest first, each with a kind (trade | thesis | launch | burn), a stable id and a timestamp. ?since= (unix seconds) returns only what is newer; ?limit= 1-200 (default 100). Poll it every few seconds; ask with since a minute behind what you last saw, because the indexer runs behind the chain.
POST /api/profile · POST /api/profile/pfp · POST /api/thesis · POST /api/thesis/delete · POST /api/thesis/like · POST /api/follow · POST /api/crew · POST /api/crew/join · POST /api/telegram/link
The only writes, and none of them is anonymous: each body is authorised by an EIP-191 personal_sign signature from the wallet it concerns, over a fixed text that spells out the exact change (the site builds it; identidad.js is the reference). Signed text always names the thing, never its database id: you sign “Join the crew ‘Gatos’”, not a number you cannot check. A thesis, and a like on one, also require a non-zero balance on chain at that moment. Names are unique (case-insensitive, 409 when taken) and can change once every 30 days (429 with Retry-After). Pictures are PNG, JPEG or WebP up to 512 KB and 2048 px, and are served with a fixed content type. Every write is rate-limited per wallet and per IP.

Limits, caching and what we promise

  • Rate limit. 300 requests per minute per IP. Over it you get 429 with a Retry-After header. The limit is generous on purpose and enforced approximately: it exists to stop scraping, not to police normal use.
  • Cache. Responses carry Cache-Control; most are good for 10-30 seconds at the edge. Honour it — polling faster gets you the same bytes and counts against your limit.
  • Freshness. The indexer runs every minute. /api/stats reports its cursor and the chain head so you can see how far behind it is.
  • Degraded mode. If our database is unavailable, most reads are served from a snapshot in object storage and the response carries X-AGI-Degradado with the timestamp of that snapshot. The live-trades endpoint is the exception: it fails rather than serve stale data, because a frozen "live" feed is worse than none.
  • Stability. We will add fields without warning and we will try not to remove or rename them. This is a best-effort promise from a small project, not an SLA: if you build something that matters on it, pin what you read and handle a field going missing.
  • No authority. If our numbers and the chain disagree, the chain is right. Nothing here should be the only source for a transaction you sign.
  • One gotcha. Cloudflare's bot protection sits in front of this Worker and rejects some default user agents with a 403 — Python's urllib is one of them. Send any user agent of your own and it goes through.

An example

curl 'https://api.artificialgatointelligence.com/api/launches?limit=5&sort=volume'

Nothing that moves money goes through this API. Launching a token, trading and claiming fees are transactions you sign against the contracts — see Launching a token, Trading on the curve and Claiming fees.