Skip to content
Build / API reference

API reference

A public JSON API over HTTPS: markets, clusters, agents, mandates, stats, a live event stream, and unsigned transaction builders.

Conventions

  • Base URL: https://nofomoagent.com/api/v1. All responses are JSON; the shapes are published as TypeScript in lib/api/types.ts.
  • Money on the wire is a decimal string in ETH ("0.00012") to avoid float loss. USD values are numbers and always optional.
  • Times are unix seconds. Addresses are checksummed 0x strings.
  • Cluster ids are ${deployment}-${blockId}, for example current-3 or legacy-1. They are stable forever.
  • Every list is a Page<T>: { items, next, indexedBlock }. Pass next back as cursor until it is null. indexedBlock is the chain height the data is consistent with.
  • No API key. Reads are open to any origin (CORS *).

Errors, limits, caching

Errors use HTTP status codes and one body shape:

ApiError
{ "error": { "code": "not_found", "message": "Cluster current-99 not found" } }

Rate limits are per client IP and per class of route: generous for reads, tighter for transaction builders and stream connections. A limited request gets 429 with a Retry-After header; X-RateLimit-Remaining is exposed on responses. Read routes send Cache-Control with a short s-maxage and stale-while-revalidate (a few seconds for clusters and stats, longer for cleared clusters, which never change). Transaction builders are never cached.

Markets

GET/api/v1/markets

Markets the router accepts, as Page<Market>: listed Robinhood Stock Tokens (kind: "stock", venue stock-v3) and recent Pons V2 launch curves (kind: "pons"). tradable is true only for markets that can be cleared right now. Stocks also carry restricted: true, blocker (why the venue refuses to trade it now: paused, corporate action pending, or null), sharesPerToken (the ERC-8056 multiplier: shares = raw tokens x multiplier) and priceUsd. Prices are per whole raw token.

ParameterDescription
kindstock or pons.
qSearch by symbol, name, market or token address.
tradabletrue or false.
sortreserve (default) or new.
limitPage size. Defaults and maximums vary per route (for example 25 and 100 on clusters).
cursorOpaque cursor from the previous page's next field.

GET/api/v1/markets/{market}

One Market. capacityEth lists the largest buy that stays within a few common ceilings.

Market (trimmed)
{
  "market": "0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC",
  "token": "0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC",
  "symbol": "NVDA",
  "name": "NVIDIA",
  "venue": "stock-v3",
  "kind": "stock",
  "restricted": true,
  "blocker": null,
  "sharesPerToken": 1.000775,
  "priceEth": 0.0834,
  "priceUsd": 225.6,
  "reserveEth": 1433.5,
  "capacityEth": [{ "ceilingBps": 100, "eth": "166.32" }],
  "openClusterId": null,
  "tradable": true
}

Clusters

GET/api/v1/clusters

Page<Cluster>, newest first, across both deployments.

ParameterDescription
statusFORMING, CLEARABLE or CLEARED.
marketMarket address (stock token or Pons curve).
walletOnly clusters this wallet joined.
deploymentcurrent or legacy.
limitPage size. Defaults and maximums vary per route (for example 25 and 100 on clusters).
cursorOpaque cursor from the previous page's next field.
bash
curl 'https://nofomoagent.com/api/v1/clusters?status=FORMING&limit=5'

GET/api/v1/clusters/{id}

One Cluster including participants. Once cleared, result carries the uniform price and the numbers explained in clearing math.

Cluster (trimmed)
{
  "id": "current-3",
  "status": "CLEARED",
  "symbol": "EXAMPLE",
  "closesAt": 1790000000,
  "ceilingBps": 300,
  "wallets": 4,
  "totalJoinedEth": "0.2",
  "result": {
    "totalInEth": "0.2",
    "fillRatio": 1,
    "feeEth": "0.0002",
    "uniformPriceEth": 0.00000037,
    "impactBps": 84,
    "raceWorstBps": 131,
    "clearTx": "0x…"
  },
  "participants": [
    { "wallet": "0x…", "amountEth": "0.05", "tokensOut": "…", "refundEth": "0", "claimed": false }
  ]
}

Values above are placeholders showing the shape, not real data.

Agents

GET/api/v1/agents

Page<AgentSummary>: every wallet that joined a cluster or is named as an originator, with clusters joined and opened, capital, mean impact, mean cluster size and active mandates.

ParameterDescription
limitPage size. Defaults and maximums vary per route (for example 25 and 100 on clusters).
cursorOpaque cursor from the previous page's next field.

GET/api/v1/agents/{address}

AgentDetail: the summary plus recentClusters and mandatesAsOriginator.

Mandates and executions

GET/api/v1/mandates

Page<Mandate> with limits, balance and today's spend.

ParameterDescription
allocatorFilter by allocator.
originatorFilter by originator.
activetrue or false.
limitPage size. Defaults and maximums vary per route (for example 25 and 100 on clusters).
cursorOpaque cursor from the previous page's next field.

GET/api/v1/executions

Page<MandateExecution>: each execution with its per-mandate fills.

ParameterDescription
originatorFilter by originator.
allocatorOnly executions that filled this allocator.
idOne execution, for example current-4.
limitPage size. Defaults and maximums vary per route (for example 25 and 100 on clusters).
cursorOpaque cursor from the previous page's next field.

Stats, analytics, network

GET/api/v1/stats

Stats: clusters cleared and forming, capital cleared, unique wallets, active mandates, armed ETH, last clear time and the indexed block. ethUsd is for display and may be null.

bash
curl https://nofomoagent.com/api/v1/stats

GET/api/v1/analytics

AnalyticsSeries: one row per cleared cluster with wallets, size, impact, race counterfactual, fill ratio and seconds from open to clear.

GET/api/v1/network

NetworkGraph: agents as nodes; two agents share an edge when they cleared in the same cluster, weighted by how many times.

Live stream (SSE)

GET/api/v1/stream

Server-Sent Events. Each message has event: <type> and data: <json>. Reconnects resume with the standard Last-Event-ID header.

Browser or Node 22+
const es = new EventSource("https://nofomoagent.com/api/v1/stream");
es.addEventListener("cluster.cleared", (e) => {
  const { cluster } = JSON.parse(e.data);
  console.log(cluster.id, cluster.result.uniformPriceEth);
});
EventPayload
hello, heartbeatindexedBlock, at
cluster.openedcluster
cluster.joinedclusterId, wallet, amountEth, totalEth, tx, at
cluster.leftclusterId, wallet, amountEth, tx, at
cluster.clearedcluster (with result)
cluster.claimedclusterId, wallet, tokens, refundEth, tx, at
mandate.armedmandate
mandate.revokedmandateId, returnedEth, tx, at
mandate.executedexecution

Transaction builders

POST/api/v1/tx/{kind}

Returns an unsigned PreparedTx for your wallet or agent to sign and send. NoFomo never signs. Inputs are validated against the contracts' rules and live chain state; a failed check returns 422 with a specific code (for example cluster_closed). A clear that would revert right now (for example outside the price guard) returns 409 with the reason. Stock-market entries from a restricted country return 451 (see below).

kindBody
openmarket, windowSec? (10 to 3600, default 60), ceilingBps? (10 to 2000, default 300), amountEth? (0, or at least 0.000001)
joinclusterId, amountEth (at least 0.000001)
leaveclusterId, wallet?
clearclusterId (the PreparedTx carries a suggested gas limit)
claimclusterId, wallet? (returns claimTokens if your tokens were parked)
claim-tokensclusterId, wallet?
claim-forclusterId, wallet
armoriginator, amountEth, perExecEth, dailyCapEth, ceilingBps, expiry?, market?, maxSpotEth?
top-upmandateId, amountEth
revokemandateId
bash
curl -X POST https://nofomoagent.com/api/v1/tx/join \
  -H 'content-type: application/json' \
  -d '{ "clusterId": "current-12", "amountEth": "0.01" }'
PreparedTx
{
  "chainId": 4663,
  "to": "0x…BlockClearing",
  "data": "0x…",
  "value": "10000000000000000",
  "description": "Join NoFomo cluster current-12 (…) with 0.01 ETH escrow; … NoFomo contracts are unaudited (internal review only).",
  "gas": "3900000"
}

value is wei as a decimal string. Show description to whoever signs. gas, when present, is a suggested gas limit: send at least that much (a stock clear walks pool ticks and uses about 3M gas on USDG routes; an under-gassed clear reverts and can be retried).

Geo and stock restrictions

GET/api/v1/geo

{ country, stocksBlocked, blocked }: the request's country as our hosting edge reports it (ISO code, or null), whether stock markets can be traded from there, and the blocked list with reasons. Never cached.

Robinhood Stock Tokens are not offered to US Persons and are prohibited or restricted in some jurisdictions. From a listed country, open and join on a stock cluster, arm on a stock market or without a market binding, and top-up of such a mandate return 451 with code restricted_jurisdiction. The remote MCP server applies the same rule. Exits (leave, clear, claim, revoke) are never blocked. IP geolocation is a control, not a guarantee; see the Terms.

451
{ "error": { "code": "restricted_jurisdiction", "message": "Opening a cluster on NVDA: Stock markets can't be traded from United States. …" } }

Health

GET/api/health

{ ok, indexedBlock, rpcLatencyMs }. Never cached. Use it for uptime checks.

Cookie settings

Choose what we may store on this device. You can change this at any time from the footer.

  • Strictly necessary

    Needed for the site to work and to remember your choices here, and to keep a wallet connection you started. These can't be switched off.

  • Preferences

    Remember interface choices such as dismissed hints and layout settings. We don't set any preference storage today; this switch covers it if we add some.

  • Analytics

    Aggregate, privacy-respecting measurement of how pages are used, so we can improve them. No analytics run today, and none will run unless you allow them here.

Full list of every cookie and storage key: cookie policy.