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 inlib/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 examplecurrent-3orlegacy-1. They are stable forever. - Every list is a
Page<T>:{ items, next, indexedBlock }. Passnextback ascursoruntil it isnull.indexedBlockis 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:
{ "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.
| Parameter | Description |
|---|---|
kind | stock or pons. |
q | Search by symbol, name, market or token address. |
tradable | true or false. |
sort | reserve (default) or new. |
limit | Page size. Defaults and maximums vary per route (for example 25 and 100 on clusters). |
cursor | Opaque 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": "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.
| Parameter | Description |
|---|---|
status | FORMING, CLEARABLE or CLEARED. |
market | Market address (stock token or Pons curve). |
wallet | Only clusters this wallet joined. |
deployment | current or legacy. |
limit | Page size. Defaults and maximums vary per route (for example 25 and 100 on clusters). |
cursor | Opaque cursor from the previous page's next field. |
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.
{
"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.
| Parameter | Description |
|---|---|
limit | Page size. Defaults and maximums vary per route (for example 25 and 100 on clusters). |
cursor | Opaque 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.
| Parameter | Description |
|---|---|
allocator | Filter by allocator. |
originator | Filter by originator. |
active | true or false. |
limit | Page size. Defaults and maximums vary per route (for example 25 and 100 on clusters). |
cursor | Opaque cursor from the previous page's next field. |
GET/api/v1/executions
Page<MandateExecution>: each execution with its per-mandate fills.
| Parameter | Description |
|---|---|
originator | Filter by originator. |
allocator | Only executions that filled this allocator. |
id | One execution, for example current-4. |
limit | Page size. Defaults and maximums vary per route (for example 25 and 100 on clusters). |
cursor | Opaque 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.
curl https://nofomoagent.com/api/v1/statsGET/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.
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);
});| Event | Payload |
|---|---|
hello, heartbeat | indexedBlock, at |
cluster.opened | cluster |
cluster.joined | clusterId, wallet, amountEth, totalEth, tx, at |
cluster.left | clusterId, wallet, amountEth, tx, at |
cluster.cleared | cluster (with result) |
cluster.claimed | clusterId, wallet, tokens, refundEth, tx, at |
mandate.armed | mandate |
mandate.revoked | mandateId, returnedEth, tx, at |
mandate.executed | execution |
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).
| kind | Body |
|---|---|
open | market, windowSec? (10 to 3600, default 60), ceilingBps? (10 to 2000, default 300), amountEth? (0, or at least 0.000001) |
join | clusterId, amountEth (at least 0.000001) |
leave | clusterId, wallet? |
clear | clusterId (the PreparedTx carries a suggested gas limit) |
claim | clusterId, wallet? (returns claimTokens if your tokens were parked) |
claim-tokens | clusterId, wallet? |
claim-for | clusterId, wallet |
arm | originator, amountEth, perExecEth, dailyCapEth, ceilingBps, expiry?, market?, maxSpotEth? |
top-up | mandateId, amountEth |
revoke | mandateId |
curl -X POST https://nofomoagent.com/api/v1/tx/join \
-H 'content-type: application/json' \
-d '{ "clusterId": "current-12", "amountEth": "0.01" }'{
"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.
{ "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.