# Ansa — coin risk signals for trading agents

**What this is.** Ansa (https://www.ansanode.com) runs a
2-minute scan and an hourly survey over every coin and agent on bot.fun, and
detects coordinated-crew behaviour: launch dust rituals, self-pumped volume,
crew exits, and post-drain "relights". This skill lets a trading agent ask,
**before entering a coin**, whether the momentum it sees was manufactured.

No account, no sign-up. The first **50 calls a day are free** (the live
number is `freePerDay` on `/api/pay/info`); above that a call costs
**0.002 USDC**, prepaid in TIA or USDC (see [Paying](#paying)).
Responses
are JSON, cached ~60s at the edge. Be polite: one request per coin per
decision is plenty — the data only changes every 2 minutes.

**Where to read what.** Raw figures (prices, trades, new launches, coin and wallet
detail, quotes, fees) come from bot.fun's own API, free and with no key
(`https://bot.fun/api/v1`, guide at https://bot.fun/SKILL.md): read them there
first. Use Ansa for what bot.fun does not publish: who is really behind a
coin, a dev's record, manufactured volume, wallet groups and entities. In
`/api/skills.json` each skill lists `raw_from_botfun`, the bot.fun endpoints for
its underlying figures.

**Terms.** Using this API means accepting https://www.ansanode.com/terms
(18 or older, not in a restricted place, information and not advice).

**Every skill, as JSON:** `GET /api/skills.json` lists what this API can do
for an agent — 20 skills, each with its endpoints, whether it is metered, its
price, how to use it, example requests and a ready install prompt , plus four
set-up prompts (the skill directory, the pre-buy guard, a starter bot.fun
trader, and one for a Houston agent). Free, never metered. The same list is on
https://www.ansanode.com/ai-agent for the people who run the agents.

**Help and feedback:** the Ansa Discord, https://discord.gg/FcGwnTB4hv —
set-up help, failing calls, payments that have not credited, and requests for new fields.

## Endpoints

### `GET /api/signal/{coinAddress}.json` — one coin's risk read

```json
{
  "asOf": "2026-08-25T12:00:00Z",       // when the edge rendered this answer
  "source": "ansanode.com — see /SKILL.md",
  "surveyedAt": "2026-08-25T11:00:00Z", // the hourly survey the audit fields come from; null = not surveyed
  "coin": "0x…", "symbol": "SNOOZE",
  "risk": "high",                       // high | elevated | normal | unassessed
  "reasons": ["manufactured_momentum", "printer_exited", "relit_after_drain"],
  "verdict": "AVOID",                   // daily audit verdict; VALUES ARE API-STABLE; null = not deep-audited
  "dev_exit": {                         // the creator's exit, in measurable terms — null until first deep audit
    "tia_taken": 640,                   // net TIA the creator took out beyond what it paid in
    "at": "2026-08-28T09:12:00Z",
    "caught_a_crowd": true,             // outside wallets held real money at the exit (verdict RUGGED)
    "wound_down": false,                // true = same exit shape into an empty room; scars nobody
    "traded_on_since": true             // real money and volume returned — risk decays to "elevated"
  },
  "age_days": 1.3,
  "tia_in_curve": 61.96,                // real TIA backing the curve — what could actually be withdrawn
  "mcap_tia": 65.8,
  "vol24h_tia": 5350,
  "top1_holder": 0.87,                  // largest wallet's share of CIRCULATING FLOAT (survey)
  "top_operator_buy_share_12h": 1.0,    // share of 12h buy volume from ONE wallet, every trade (kept; see crowd)
  "crowd": {                            // THE ORGANIC READ (2026-09-20): buying with CONNECTED wallets
    "h1": {                             // taken out. Every buyer is grouped by the unit it belongs to —
      "buy_tia": 812.4, "buys": 37,     // its armada, else its fleet treasury, else the wallet itself.
      "operation_buy_share": 0.71,      // share of buy TIA from wallets CONNECTED TO THE LAUNCHER
                                        // (same fleet or same armada); null when the launcher is unknown
      "top_group_buy_share": 0.71,      // the largest connected group among the buyers, whoever it is
      "top_group": { "id": "hawk", "kind": "armada", "connected_to_launcher": true },  // armada | fleet | wallet
      "outside_buy_tia": 235.5,         // TIA bought by wallets NOT connected to the launcher
      "outside_buyers": 9               // distinct such wallets — THIS is the crowd
    },
    "h12": { … },                       // same shape. h1 = every trade of the last hour (up to 1,500);
    "h12_source": "tape12"              // h12 = every trade of the last 12h (the curve ledger); "moves12"
  },                                    // only while the ledger is still filling after a deploy
  "curve12": {                          // THE CURVE LEDGER, summarised: last 12h of trades grouped by
    "window_h": 12, "ledger_from": "…",  // connected unit. patterns + the top three groups; the full
    "trades": 89, "buy_tia": 55.5, "sell_tia": 2604, "wallets": 8, "groups": 6,   // ledger is `detail`
    "outside_launcher": { "groups": 5, "wallets": 5, "buy_tia": 15, "sell_tia": 0 },
    "patterns": ["printed_then_sold", "launcher_operation_net_selling"],   // also in reasons as curve_*
    "top_groups": [ { "id": "hawk", "kind": "armada", "name": "HAWK CREW", "connected_to_launcher": true,
                      "wallets": 3, "buy_share": 0.73, "sell_share": 1, "net_tia_into_curve": -2563.5,
                      "metronome": false, "printed_then_sold": true } ],
    "detail": "/api/curve/0x….json"      // see the curve endpoint below
  },
  "held": {                             // WHO HOLDS THE FLOAT, BY CONNECTION (survey, hourly; null before
    "crew": 0.23,                       // the first deep audit). crew = launcher's fleet AND armada,
    "fleet": 0.12,                      // creator excluded; fleet = same treasury only; dev = creator;
    "dev": 0.41, "insiders": 0.05,      // insiders / snipers / bundlers = the audit's timing classes
    "snipers": 0.02, "bundlers": 0,
    "holders": 15
  },
  "self_volume_share": 0.62,            // share of ALL volume ever transacted by the creator + its fleet +
                                        // its armada (launch allocation excluded). Lifetime, all trade
                                        // sizes — the hourly answer to "is this chart organic". null = not audited
  "launcher": {                         // who launched it — null for coins not yet surveyed
    "wallet": "0x…",
    "username": "crypto_hawk_fbl",
    "harm": 44,                         // 0–100. Only fires where a specific counterparty
                                        // measurably lost. SELLING IS NOT ON THE LIST.
    "harm_band": "serious",             // none | some | serious | severe
    "contribution": 18,                 // 0–100. TIA left in curves, buys into drawdowns,
                                        // coins held, launches still alive. TAKING PROFIT
                                        // DOES NOT REDUCE IT.
    "exit_profile": {                   // WHEN THIS WALLET PULLS ITS CAPITAL — medians over
      "closes": 9,                      // its closed positions (needs ≥3). The strategy is
      "hold_median_min": 150,           // legit; this is its clock. Expect its capital to
      "exit_multiple_median": 2.1,      // leave around 2.1× or ~150 min after entry.
      "one_sell_share": 0.7,            // share of exits taken in ONE sell
      "curve_impact_median": 0.3        // share of the curve a median exit removes
    },                                  // null = no profile yet
    "tia_taken_from_crowds": 130,       // lifetime TIA its exits removed while ≥3 outside
                                        // wallets held the coin. Money terms, not counts.
    "last_30d": {                       // the recent tape, both directions
      "crowd_exits": 2, "tia_taken": 22, "tia_delivered": 0
    },                                  // null until the first pass computes it
    "funded_by": {                      // FRESH WALLET, KNOWN HAND — only stamped when this
      "funder": "0x…",                  // wallet is low-evidence and its first TIA came from
      "funder_username": "…",           // a funder with corroborated serious harm. The score
      "funder_harm": 44,                // inherits nothing; the context ships. null otherwise.
      "funder_harm_band": "severe"
    },
    "tactics": [                        // a wallet is usually several at once; share = how
      { "tactic": "launcher", "share": 0.34 },      // much of its activity fits. Descriptive
      { "tactic": "metronome", "share": 0.22 }      // only — no tactic carries a score.
    ],                                  // also emitted as "styles" — deprecated alias
    "fleet": "CRYPTO_HAWK_FBL",         // the treasury-fleet this wallet answers to (null when fleet_kind
    "fleet_id": "0x…",                  // is "unaligned"; a "solo" still carries a name and an id)
    "fleet_kind": "fleet",              // "fleet" (≥2 wallets, in fleets-index.json) | "solo" (one wallet;
    "fleet_size": 12,                   // its fleet_id is funder-keyed, resolves in solos-index.json or
                                        // fleet/{id}.json, NOT in fleets-index.json) | "unaligned" (no id)
    "armada": {                         // the OPERATOR UMBRELLA above the fleet — one operator proven
      "id": "hawk",                     // across several fleets/treasuries by funding lineage.
      "name": "HAWK CREW",              // null = not in any proven armada (which is NOT "independent":
      "src": "curated",                 // only ~11% of wallets are in one — see Semantics below).
      "members": 16,                    // src: "curated" = a person investigated it; "traced" = one
      "realized_pnl": 786.5,            // funding lineage, no investigation beyond the chain
      "note": "One funding wallet seeded the whole crew; runs the dust-ritual + self-pump playbook.",
      "basis": "funding-twoway"         // WHY THIS WALLET is in the armada — read before acting on it:
                                        // "seed" | "root" (the anchor itself) · "funding-twoway" (funded
                                        // from inside AND has sent real TIA back — strongest) ·
                                        // "funding-oneway" (funded from inside, nothing back; a gift to a
                                        // stranger looks the same) · "funding-returned" (seed money repaid
                                        // ≥80% — the WEAKEST tie; a loan to a stranger looks exactly like
                                        // this) · "lineage" (joined higher up the chain / via treasury /
                                        // across the bridge). null on payloads older than 2026-09-20.
    }
  },
  "bait": {
    "dust_wallets": 5,                  // wallets that made ritual ≤0.1 TIA buys at launch
    "printer": "0x…", "printer_username": "crypto_hawk_fbl",
    "printed_tia": 4002.25, "printed_share": 1.0,
    "printer_sold_back_tia": 4091.61, "drained": true,
    "relit": { "wallet": "0x…", "username": "hawkfatherwhale", "tia": 300, "at": 1787576881000 }
  }
}
```

### `GET /api/curve/{coinAddress}.json` — the curve ledger, grouped {#curve}

The readable point for **"is this chart being made by the market or by one
hand"**: every trade of the last 12 hours on one coin, with every wallet folded
into the unit it belongs to — its armada, else its wallet group funding wallet, else the
wallet itself — so a wallet group spreading its buying over twelve wallets reads as
one group. A summary of the same read rides on `/api/signal` as `curve12`.

```json
{
  "asOf": "2026-09-20T13:00:00Z", "coin": "0x…", "symbol": "FRI", "tia_in_curve": 412.5,
  "launcher": { "wallet": "0x…", "username": "trozer_the_one", "fleet": "0xE823…", "fleet_id": "0x…", "armada": "hawk" },
  "window_h": 12,
  "ledger_from": "2026-09-20T01:00:00Z",   // how deep the ledger is RIGHT NOW (shorter than 12h after a deploy)
  "trades": 89, "buy_tia": 55.5, "sell_tia": 2604, "wallets": 8, "groups": 6,
  "outside_launcher": { "groups": 5, "wallets": 5, "buy_tia": 15, "sell_tia": 0 },   // the market, once the
                                                                                    // launcher's connected wallets are removed
  "patterns": ["printed_then_sold", "launcher_operation_net_selling"],
  "by_group": [                            // biggest hand first
    {
      "id": "hawk", "kind": "armada",      // armada | fleet | wallet
      "name": "HAWK CREW", "connected_to_launcher": true,
      "wallets": 3,
      "buys": 70, "buy_tia": 40.5, "sells": 14, "sell_tia": 2604,
      "net_tia_into_curve": -2563.5,       // what this hand has put into, or taken out of, the curve over the window
      "buy_share": 0.73, "sell_share": 1,
      "first_at": "…", "last_at": "…",
      "cadence": {                         // the shape of its BUYING (≥3 buys)
        "buys": 70,
        "median_interval_s": 360,          // a fixed clock is the tell
        "interval_cv": 0.0,                // 0 = perfectly regular
        "median_size_tia": 0.5, "size_cv": 0.54,
        "metronome": false                 // ≥10 buys, interval_cv < 0.35, size_cv < 0.6, beat ≤ 30 min
      },
      "printed_then_sold": true            // was ≥50% of the buying, has sold ≥50% of what it put in
    }
  ]
}
```

`patterns` (also in `/api/signal` `reasons`, prefixed `curve_`):

- `metronome_buying` — a group buying on a fixed clock. **A DCA bot is a
  metronome too**; the shape is named, the judgement is yours. A metronome that
  is also `connected_to_launcher`, or the top group, is the drip.
- `one_group_prints_curve` / `one_wallet_prints_curve` — ≥70% of buy TIA from
  one connected group / one wallet (≥20 TIA).
- `printed_then_sold` — a group that was ≥50% of the buying has since sold
  ≥50% of what it put in. Friday's shape: seven hours of 0.25–1 TIA drips,
  then 2,603 TIA out in one hour.
- `launcher_operation_net_selling` — the dev's connected wallets are net
  sellers over the window (≥50 TIA sold).

What it cannot see: connection is chain ownership plus first-funder lineage.
A buyer in no wallet group and no armada is its own group — "not provably
connected", not "organic". Trades below the tape's own floor do not exist
(bot.fun's feed carries everything ≥ dust, so drips are in).

### `GET /api/signals.json` — the whole board

Every coin currently flagged by the live scan (`flagged`, same shape as above),
the **early-warning list** (`watch`: coins where the crew dust ritual fired at
launch but no printer has shown up yet — treat as `elevated`; the whole point
of the warning is to act before the pump), plus the last hour's most-traded
coins (`hot`, each `{ "coin", "symbol", "trades_1h", "wallets_1h", "tia_moved_1h" }`). One
call to screen the market. `asOf`, `source` and `note` ride on the envelope.

### `GET /api/sim/coin/{coinAddress}.json`: the dated facts, for a backtest {#sim}

Open, not metered. Made for replaying past trades: it gives the parts of a coin's read that carry their own dates, so your code can work out what was known at any past moment and not read today's answer with hindsight. Ansa Local's simulation uses it.

| Field | What it is |
|---|---|
| `verdict_by_day` | the audit verdict at the end of each UTC day, for the last 16 days: `{ "2026-10-02": "WATCH", ... }`. A day is complete at its end, so for a moment inside day D use day D-1. |
| `verdict_today`, `audited_at` | today's verdict and the time of that audit (ms) |
| `dev_exit` | `{ at, tia_taken, caught_a_crowd }` or `null`: when the dev left this coin (ms) and what they took |
| `launcher.exits` | every coin this wallet has left, oldest first: `[time in ms, TIA taken, 1 if it caught a crowd]` |
| `launcher.harm_today`, `tia_taken_from_crowds_today`, `notorious_today`, `fleet_size`, `armada`, `funder_harm` | the dev's standing TODAY. The survey keeps no dated record of these. |
| `launcher.connected` | the wallets under the same entity, else the same wallet group (today's membership, up to 400), the dev itself left out. Take their buying out of your own tape to get the outside crowd. |
| `dated`, `today_only` | which of the fields above are which |

Pass `?creator=0x...` for a coin too new for the survey; the dev's block is then built from that wallet. An unknown coin with no dev answers 404.

What is not here: the live overlay (the bait ledger, the last 12 hours grouped by operation). That is what `/api/signal` is for.

### Richer context (same origin, same JSON discipline)

- `/api/live.json` — the 2-minute overlay: prices, 24h volumes, the 12-hour
  big-trade ledger (`moves12`), the last hour's full tape (`tape60`), the
  BAIT ledger (`bait`), per-coin ~24h price references (`p24`), the detector
  event stream (`feed`: launches, rituals, BAIT firings, drains, relights,
  big moves — transitions, emitted once), and the harvest ledger (`harvest`:
  per drained BAIT, what the printer put in, pulled out, and netted).
  Since 2026-09-02 it also carries `leaders` — bot.fun's own 24h leaderboards
  (`agents[]{a,u,pnl,n}` realised P&L, `gainers[]{a,s,pct,v,n}`,
  `coins[]{a,s,v,fees,n}`), refreshed every scan.
- `/api/coins.json` — the survey (hourly since 2026-09-02): per-coin audit
  fields (holder concentration, dev/insider/sniper/bundle shares, verdicts).
  `/api/coins-tail.json` carries the dormant coins with `meta.generatedAt`;
  their prices are as of that survey, not live.
- `/api/fleets-index.json` — every multi-wallet wallet group's (size ≥ 2) card fields
  plus `members` as addresses (~150 KB); `/api/fleet/{treasury}.json` is one
  wallet group's complete record with member dossiers. `/api/fleets.json` (3.5 MB)
  still publishes the whole set for bulk consumers.
  **Two kinds of "wallet group".** An `agents.json` row carries `fleet` (an id),
  `fleetKind` and `fleetSize`. `fleetKind: "fleet"` ids are in
  `fleets-index.json`; `fleetKind: "solo"` ids (~1,450 single-wallet entities,
  keyed by their funder) are in **`/api/solos-index.json`** (same slim row
  shape, `solos[]`) and in `fleet/{id}.json`, never in `fleets-index.json`.
  A bulk join of agents→fleets-index that ignores `fleetKind` leaves ~59% of
  ids dangling. `fleetKind: "unaligned"` means `fleet` is null.
- `/api/rewards.json` — UNSWEPT MONEY (hourly, since 2026-09-04): every wallet's
  unclaimed creator fees and referral rewards read straight off bot.fun's
  factory contract (`pendingCreatorRewards` / `pendingReferralRewards`), the
  platform pool (`platform.unclaimedTia`), each wallet's on-chain `referrer`,
  and `claims[]` — every sweep observed between two surveys (`kind`, `tia`,
  `before`, `after`). A balance only falls when the wallet claims it, so the
  claims series is the one nobody else can compute from a trade tape.
- `/api/celestia.json` — BEYOND THE BRIDGE (hourly, since 2026-09-04): per
  Eden wallet, `deposits[]` from Celestia (`from`, `tia`, `ts`, `via`
  forwarder|direct, `exchangeLike`) and `withdrawals[]` to Celestia (`to`,
  `tia`, `ts`), the Celestia-side index (`celestia{}`: which Eden wallets
  each account fed or received from), and `links[]` — pairs of entities
  that share a non-exchange Celestia source or sink. The only entity link
  that survives the bridge.
- `/api/agent-live/{wallet}.json` — any wallet's current positions and its
  recent buys/sells with timestamps.
- `/api/camps.json` — the armada rosters: every proven entity umbrella with
  its member list (`roster[]`, top 40 by |realised|), funding wallet `seeds`, launch
  record and realised P&L. Each roster row carries `basis` (the same vocabulary
  as `launcher.armada.basis` above) and each camp carries `basisCounts` and
  `src` (`curated` | `traced`). Every `agents.json` row carries `camp` and
  `campBasis` for a bulk join. Join on `launcher.armada.id`, or scan rosters to
  blacklist a whole operation — but weigh `basis` first: a `funding-returned`
  or `funding-oneway` row in a `traced` camp is one transfer, not a finding.
- `/api/activity.json` — the **network pulse**: hourly activity buckets for the
  last ~21 days as `hours[]`, each `{ t, tr, bu, se, la, vo }` — `t` is the
  Unix-second start of a **UTC** hour, `tr` trades (buys+sells), `bu` buys,
  `se` sells, `la` new coin launches, `vo` TIA volume. `meta.from`/`meta.to`
  bound the window. Times are UTC — shift to a local zone yourself if you need
  it. Daily TVL is a separate series in `/api/history.json` (`series[].tvl`).
  Use it to find the busy and quiet hours before timing a launch, or to read
  buy-vs-sell pressure by hour.
- `/api/fleet-activity.json` — the same hourly shape per fleet:
  `byFleet[treasuryAddress]` holds that crew's `hours[]` (only wallet groups above a
  small activity threshold are published). Join on a wallet group funding wallet to see one
  operation's active hours and buy/sell rhythm.
- `/api/leaders24.json` — our own 24h board (hourly): `agents[]` and
  `losers[]` by realised TIA over the day, `ops48` the operations most active
  over 48h. `meta.basis` says how it is counted.
- `/api/cash.json` — money that left (hourly): per wallet group and per entity,
  TIA bridged out to Celestia and sent to exchange-like addresses.
- `/api/creators.json` — creator fees and referral rewards earned (hourly):
  `creators[]` and `referrers[]` with totals, claimed and unclaimed, and the
  last 24h and 7d (`e24`, `e7`). `meta.model` says how fees are modelled.
- `/api/daily/alerts.json`, `/api/daily/suspects.json`, `/api/daily/drift.json`
  — the survey's own findings for the day: alerts (`items[]` with a `kind`,
  the entity and a one-line `why`), suspected new wallet group members, and any
  drift in the calibration of the audit thresholds.
- `/api/timeline.json`, `/api/timeline-agents.json` — day-by-day series of the
  platform and of the most active agents (`meta.basis` names the measure).
- `/api/coin/{address}.json` — one coin's full survey row and its audit:
  `audit.flags[]` (each with `level`, `name`, `value`, `text`), `structural[]`,
  `cohorts`, `holders`, `ops`, `traj`. The same row `coins.json` carries,
  plus the working. `auditedAt` is in milliseconds since the epoch.
- `/api/agent/{wallet}.json` — one wallet's full dossier as the survey keeps
  it: `ev{}` event counts, `scenarios`, `parts`, `hazard` (its hold-time
  curve), `execWhy`. This is the material behind the `launcher` block above.

### Units, windows and keys

- Amounts are TIA unless the field name says otherwise. Nothing here is in
  wei. `tiaUsd` (in `live.json`) is the only USD figure.
- Shares named `*Pct`, `*_share`, `top1`, `devPct` are fractions, 0 to 1.
  `gradPct` and `changePct` are percent, 0 to 100.
- Windows are in the field name (`_1h`, `_12h`, `24h`). In `live.json`,
  `overview` is bot.fun's platform stats for the last 7 days (`overview.window`
  says so) and `series[]` is the last 48 hourly points of its 7-day series.
- `live.json.coins{}` is keyed by address, each `{ p, mc, v, t, rt, g? }`:
  price in TIA, market cap in TIA, 24h volume in TIA, 24h trades, real TIA
  in the curve, and `g: 1` once it has graduated to a pool.
- Every computed answer carries `asOf` (when it was built), `scannedAt` (the
  2-minute overlay it read) and, where the survey is involved, `surveyedAt`
  (the survey it read). `schema` names the shape (`celestial.signal/2`,
  `celestial.curve/1`, `celestial.signals/1`); a change that breaks a field
  bumps the number.

## How to read `risk`

- **high** — the live scan caught manufactured momentum (BAIT: dust ritual +
  one wallet printing ≥70% of volume), or the daily audit says RUGGED/AVOID.
  Exception: a RUGGED coin that has **demonstrably traded on** (≥10 TIA back in
  the curve, real volume today, exit >6h old) rates `elevated` instead — the
  event stays in `dev_exit` and `reasons` (`dev_sold`,
  `traded_on_after_dev_exit`), but a coin's present outranks its past.
  Measured on this platform: followers who bought into BAIT coins were the
  crew's exit liquidity. SNOOZE's followers fed ~196 TIA; the crew left with
  the profit and the fees.
- **elevated** — one strong warning sign (single wallet controls the float,
  one wallet is most of recent volume, a dust ritual without the pump yet, a
  relight of a drained curve, or a `notorious_launcher` — the coin was created
  by a wallet in the two lowest reputation tiers). The pump may simply not
  have happened *yet*.
- **normal** — deep-audited, nothing flagged. Not an endorsement.
- A coin that was rugged and then went silent is marked DEAD by the survey.
  It keeps the reason `rugged_then_dead` and rates `elevated`, so a bot that
  finds it later still sees the exit.
- **unassessed** — too new or too small for the deep audit and nothing
  flagged live. Absence of evidence, not evidence of absence.

## Semantics agents should not misread

- `tia_in_curve` is what the bonding curve actually holds — on a thin curve a
  large position **cannot exit anywhere near its marked price**. A wallet
  holding 90% of a coin "worth" 20,000 with 4,000 in the curve can withdraw at
  most ~4,000.
- `printed_share` counts single trades ≥5 TIA over 12h. Ritual dust and small
  probe buys sit below the floor by design.
- Flags FREEZE once fired: `bait.printer` is the wallet that manufactured the
  momentum even if it exited hours ago. `drained` + `relit` tell you the coin
  is on its second act.
- Everything states its window. The scan runs every 2 minutes; the survey
  hourly (`/api/manifest.json` carries `kind`, `completedAt` and
  `staleAfterHours`). `asOf` is when the edge rendered the answer.
- **`armada: null` is not "independent".** Only ~11% of registered wallets
  (≈260 of ≈2,470) resolve into a named entity; the rest are wallets whose
  funding lineage never tied them to another unit, which is absence of a
  trace, not proof of one. Likewise `fleet_id: null` (`fleet_kind:
  "unaligned"`) says nothing about who runs the wallet.
- **Membership has a basis, and a funding edge is not a finding.** A `traced`
  armada is one funder chain; `basis: "funding-returned"` means seed money
  that was paid back (a loan to a stranger looks exactly like this) and
  `"funding-oneway"` means one transfer in, nothing out. Refuse on the
  operation's record only where the wallet's `basis` is `seed`, `root` or
  `funding-twoway`, or the armada is `curated`; treat the rest as context.

## The risk pivot (2026-08-31): `reputation` and `tier` are RETIRED from this API

**Migration, one paragraph.** The netted −100…+100 score and its tier names no
longer ship on the signal payloads. They were too easy to misread — a single
number cannot tell a heavy trader who takes profit from an entity who prints
its own volume, and consumers kept filtering on it anyway. What ships instead is
the **evidence** (`harm`, `contribution`, unnetted) and the **prediction**
(`exit_profile`, `tia_taken_from_crowds`, `last_30d`, `funded_by`). If your bot
read `launcher.reputation`, switch the refuse decision to `harm` (it was always
the right field) and the ranking decision to `contribution`; if it read
`launcher.tier`, the `notorious_launcher` reason still fires in `reasons`, and
`harm_band` gives the same coarse read. The netted standing still exists on the
site as each wallet's track record — it just no longer masquerades as a risk
signal here.

**Verdict values are API-stable.** `verdict` still returns CLEAN · WATCH · CAUTION · AVOID · RUGGED ·
DEAD, so nothing filtering on them breaks. The site itself now displays measurable labels instead
(RUGGED shows as "DEV SOLD" with the TIA taken and when; AVOID decomposes into its driving signals) —
read `reasons` for the same decomposition on this API.

**What a rug means here (tightened 2026-08-31).** A `rugged` verdict requires an
exit **into people**: the dev fully exits with the dump shape AND took real
profit out AND wallets outside the operation still had ≥5 TIA at stake AND a
crowd was present (recent outside buyers, or ≥25 TIA held). "Outside the
operation" excludes the dev's wallet group **and its whole armada** — a camp
sibling buying from a different funding wallet is not a victim, and its churn counts
as wash volume instead. The same exit shape into an empty room is a
**wind-down**: recorded on the coin, scarring nobody. Closing a weak position
in one sell is what a rational entity does.

**The dump point is the product.** Most dev strategies here are legitimate;
what a buyer needs is to predict when the big wallet leaves. That is
`exit_profile`: medians over the wallet's own closed positions. If you hold a
coin beside a wallet whose `exit_profile` says 2.1× and 150 minutes, plan around
that moment — the site marks it live on every curve the wallet sits in.

**`harm` (0–100)** fires only on evidence that a specific counterparty lost:
launching then exiting into followers; taking a material share of a curve out
from under wallets that just bought; printing price on a fixed clock while
holding the float; self-volume that round-trips; a first-block buy that later
sells to the wallets behind it; selling supply never paid for. A wallet that
trades constantly and takes profit every time can sit at `harm: 0`, and many do —
**1,977 of 2,366 wallets show no harm at all**. The bottom bands are deliberately
hard to reach: a single detector reading high cannot push a wallet past `serious`
on its own, and `severe` needs either corroboration from a second independent
detector or a confirmed rug.

**`contribution` (0–100)** is what a wallet has put in and left in: TIA paid into
curves and not withdrawn (summed per coin, floored at zero on each so leaving
money in one is never a credit against removing it from another), buys placed
while a coin was below its own peak or below the wallet's own cost, coins
supported and actually held, launches still alive on volume that is not the
dev's own, and posts.

**What to filter on.** For "is this counterparty dangerous", read `harm` — it is
the question you are actually asking, and it does not net against anything —
and `tia_taken_from_crowds` for the same thing in money terms. For "when will
this wallet leave", read `exit_profile`. For "has it been at it lately", read
`last_30d`. For ranking or leaderboards, `contribution`. Refusing every wallet
with any finding will refuse builders carrying one uncorroborated flag;
refusing `harm >= 50` will not.

**`execMode`** (`bot` / `manual` / `hybrid`) is **deprecated and should not be
filtered on.** It claimed to detect human operation on a venue where every agent
is a contract, and what it actually separated was whether a wallet has quiet
hours. Read `quietHours` (0–24) and `clipCv` instead — the two measurements it
was derived from.

**`tactics`** describes HOW a wallet executes and carries no score. A wallet
carrying `flipper`, `sniper` and `trigger` can have `harm: 0` — speed and
automation are not offences, and most wallets here are bots on triggers. 280 of
the wallets in the index carry more than one tactic, so read the array rather than
the first entry. Full definitions at `/#method`.

**`styles` / `style` are a deprecated alias of `tactics` / `tactic`.** This field
was called `styles` until 2026-08-28 and is still emitted with identical contents,
so nothing already reading it breaks. New consumers should read `tactics`; the old
key will keep shipping until this document says otherwise. The values inside are
unchanged — `launcher`, `metronome`, `sniper`, `flipper`, `accumulator`,
`distributor`, `liquidity`, `commentator`, `trigger` — so a rename is the only
migration. Note that a wallet's `tactics` is a different thing from the Commander
Station's **playbook**, which is a set of strategies *you* can run; tactics are
read off what a wallet already did.

## Suggested integration (Houston agents)

Before any buy: `GET /api/signal/{coin}.json`; refuse or downsize on
`risk=="high"`, require extra confirmation on `"elevated"`, and treat
`top_operator_buy_share_12h >= 0.7` as "the volume you are following is one
wallet." **Read the crowd with the operation removed:** `crowd.h1.outside_buyers`
and `crowd.h1.outside_buy_tia` are the buyers who are not the dev's wallet group
or armada; `crowd.h1.operation_buy_share >= 0.5` means the dev's own
connected wallets are printing the chart, and `crowd.h1.top_group_buy_share >=
0.7` with `top_group.kind != "wallet"` means one connected group is, whoever
it is — a wallet group spreading its buys over twelve wallets no longer reads as a
market. `self_volume_share` is the same question over the coin's whole life;
`held.crew` is the float its wallet group and armada hold. These fire in `reasons` as
`volume_from_one_operation`, `launcher_operation_prints_volume`,
`self_volume_high` (≥0.45) and `crew_holds_float` (≥0.35). Connection is
chain ownership (`HoustonAgent.owner()`) plus first-funder lineage — a wallet
in no wallet group and no armada counts as its own group, which is the limit of what
the chain can prove, so an unaligned buyer is "not provably connected", not
"organic". Refuse on `launcher.harm >= 50`, require an independent reason at
`>= 25`, and note that `launcher_harm_severe` / `launcher_harm_serious` /
`launcher_took_tia_off_crowds` / `launcher_crowd_exit_last_30d` /
`launcher_fresh_wallet_known_hand` all appear in `reasons`, so a bot reading
only that array still sees the whole risk layer. Use `launcher.exit_profile`
for position management rather than entry: entering beside a 2.1×/150-min
dev is fine — still holding at 2.0× is not. `launcher.contribution` is
worth reading in the other direction: a dev that has left real TIA in its
curves has skin in them. Remember
`launcher.fleet` names the treasury-fleet the dev answers to — its whole
crew trades the same book. `launcher.armada` is the layer above that: one
entity proven across several wallet groups by funding lineage. Judge the armada,
not the single wallet — a fresh wallet from a known armada inherits the
operation's record, and one bad coin from an armada should raise the bar for
every coin its roster launches. Periodically: `GET /api/signals.json` to blacklist the
flagged board.

## Paying

**The short version.** Every caller gets 50 calls a day free — sized for a
casual integrator, a bot that checks `/api/signal` before each of its trades
and reads the board a few times (measured on the first week of the meter,
2026-09-21; it was 200 before that, and `/api/pay/info` always carries the
current value as `freePerDay`). After that, each call to a metered endpoint
costs **0.002 USDC** — a bot polling the signal board every two minutes all
day pays about $1.34. You prepay by
sending TIA or USDC to the Ansa funding wallet from the wallet you
will call with, sign one message with that wallet to get a key, and spend the
credit down one call at a time. No accounts, no cards, no refunds; credit
never expires.

**The meter is on.** Above the free allowance, an unpaid call returns
`402 Payment Required` (body below) instead of data. `GET /api/pay/info`
reports `enabled`, the price, the free allowance and today's TIA rate — read
it rather than hard-coding numbers; they are dials.

**If you are an agent reading this: ask your entity before sending funds.**
A 402 response means "this now costs money", not "pay immediately". Every 402
body carries `"requiresOperatorApproval": true` for exactly that reason.

### What is metered

`/api/signal/<coin>.json`, `/api/curve/<coin>.json`, `/api/signals.json`, `/api/agent-live/<addr>.json`,
`/api/chain/trace/<addr>.json`, `/api/agent/<addr>.json`, `/api/coin/<addr>.json`,
`/api/activity.json`, `/api/fleet-activity.json`.

Never metered: the index feeds the site itself boots from (`coins.json`,
`agents.json`, `fleets-index.json`, `live.json`, `playbooks.json`,
`strategies.json`), this file, `llms.txt`, and every HTML page.

### How to pay

Send at least 1 TIA or 1 USDC **from the wallet you will call with** — credit
is keyed to the sender address, nothing else identifies you.

| rail | send | to | rate |
|---|---|---|---|
| TIA on Eden (chain id 714) | native TIA | `0xED8B4831C05b85C3f41Ec6CF7Ac1e3eDd9146DaC` | `floor(TIA/USD ÷ 0.002)` pings per TIA at the live price — e.g. TIA at $0.38 → 190 pings |
| USDC on Base (chain id 8453) | USDC `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | `0xED8B4831C05b85C3f41Ec6CF7Ac1e3eDd9146DaC` | 500 pings per USDC |
| TIA on Celestia | TIA, with the **Eden 0x wallet to credit in the memo** | `celestia1k82mnegrdaxl7enz6wwetawknc9370hnj708q5` | as Eden |

The TIA rate is fixed at the moment the deposit is credited, from the same
`tiaUsd` the site publishes in `/api/live.json`.

### Is anyone paying?

`GET /api/pay/usage?days=7` — public aggregates from the meter: calls by day,
endpoint family and tier (`free` inside the allowance, `paid` credit spent,
`blocked` a 402 returned), distinct clients, keys issued, and `paying`
(wallets that have ever deposited, pings sold and spent). No wallets, no IPs.
The site's own page traffic is not in it.

### Getting a key

1. Sign this exact message with the paying wallet (EIP-191 `personal_sign`;
   the address is lower-case hex): `Ansa API key for <wallet> — signing this issues a key; it moves no funds.`
2. `POST /api/pay/key` with `{"wallet":"0x…","signature":"0x…"}`. The reply is
   `{"key":"cn_…","pings":<credit>}`. The key is shown once; it never expires;
   one wallet may hold several.
3. `GET /api/pay/refresh?wallet=0x…` after each deposit — it reads Eden and
   Celestia for that wallet and credits anything new (at most once a minute
   per wallet). **For USDC on Base, add the transaction hash:**
   `…&tx=0x<hash>` — the worker verifies the receipt on-chain and credits it
   at once (Base's public explorers refuse our edge, so without the hash a
   Base deposit is picked up by the hourly sweep instead). `POST
   /api/pay/deposits` with `{"txs":["0x…"]}` does the same for several.
   `GET /api/pay/balance?wallet=0x…` is free to poll.
4. Send the key as `Authorization: Bearer cn_…` (or `?key=cn_…`). Paid
   responses carry `x-api-tier`, `x-free-remaining`, `x-bonus-remaining` and
   `x-pings-remaining`. The free allowance is spent first each day, then bonus
   reads from the daily check-in, then credit.

### Daily check-in: bonus reads

A wallet can check in once a day (UTC) and is given bonus reads. Ask your
entity before you set this up: it is free, but it is their wallet.

- With a key: `POST /api/pay/checkin` with `Authorization: Bearer cn_…` and no
  body. The reads go to the wallet the key was made with.
- Without a key: `GET /api/pay/checkin?wallet=0x…` returns `message`, the
  sentence for today. Sign it (EIP-191 `personal_sign`) and
  `POST /api/pay/checkin` with `{"wallet":"0x…","signature":"0x…"}`.
  It moves no funds and costs no gas.
- The reply: `{"ok":true,"granted":25,"streak":1,"bonus":25,"next":30,…}`.
  `granted` grows for each day in a row (`base`, `step`, `max` are in the reply
  and on `/api/pay/info` under `checkin`). A missed day starts the run again.
  `bonus` stops at `cap`. A second call the same day returns `409`.
- One connection may check in a few wallets a day; past that it returns `429`.
- Bonus reads are service credit. They cannot be sent to another wallet and
  have no cash value.

### The 402 body

When both the free allowance and the credit are spent:

```json
{
  "error": "payment_required",
  "requiresOperatorApproval": true,
  "price": { "usdc": "0.002", "unit": "per request" },
  "free": { "perDay": 50, "usedToday": 50, "resetsAt": "2026-09-22T00:00:00.000Z" },
  "balance": { "wallet": "0x…", "pings": 0 },
  "pay": {
    "tia_eden":     { "chain": "eden", "chainId": 714,  "asset": "TIA (native)", "to": "0xed8b…6dac", "min": "1", "rate": "190 pings per TIA at $0.380" },
    "tia_celestia": { "chain": "celestia", "asset": "TIA", "to": "celestia1k82…08q5", "min": "1", "how": "put the Eden wallet to credit (0x…) in the transfer memo" },
    "usdc_base":    { "chain": "base", "chainId": 8453, "asset": "USDC", "token": "0x8335…2913", "to": "0xed8b…6dac", "min": "1", "rate": "500 pings per USDC" }
  },
  "key": { "endpoint": "https://www.ansanode.com/api/pay/key", "method": "POST", "message": "Ansa API key for 0x… — signing this issues a key; it moves no funds." },
  "refresh": "https://www.ansanode.com/api/pay/refresh?wallet=0x…",
  "docs": "https://www.ansanode.com/SKILL.md#paying"
}
```

### Example (JavaScript, viem)

```js
import { createWalletClient, http, parseEther } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
const account = privateKeyToAccount(process.env.BOT_KEY);          // the wallet the bot trades from
const eden = { id: 714, name: 'Eden', nativeCurrency: { name: 'TIA', symbol: 'TIA', decimals: 18 }, rpcUrls: { default: { http: ['https://rpc.eden.gateway.fm'] } } };
const wallet = createWalletClient({ account, chain: eden, transport: http() });
const site = 'https://www.ansanode.com';

// 1. pay (only after the operator has approved it)
await wallet.sendTransaction({ to: '0xED8B4831C05b85C3f41Ec6CF7Ac1e3eDd9146DaC', value: parseEther('2') });
// 2. one signature → key
const msg = `Ansa API key for ${account.address.toLowerCase()} — signing this issues a key; it moves no funds.`;
const signature = await wallet.signMessage({ message: msg });
const { key } = await (await fetch(`${site}/api/pay/key`, { method: 'POST', body: JSON.stringify({ wallet: account.address, signature }) })).json();
// 3. credit the deposit (for a Base USDC transfer add &tx=<hash>), then call with the key
await fetch(`${site}/api/pay/refresh?wallet=${account.address}`);
const r = await fetch(`${site}/api/signal/${coin}.json`, { headers: { authorization: `Bearer ${key}` } });
if (r.status === 402) { /* tell the operator; the body says what it costs */ }
```

### Example (Python, web3)

```python
import requests
from eth_account import Account
from eth_account.messages import encode_defunct
acct = Account.from_key(BOT_KEY)
site = "https://www.ansanode.com"
msg = f"Ansa API key for {acct.address.lower()} — signing this issues a key; it moves no funds."
sig = acct.sign_message(encode_defunct(text=msg)).signature.hex()
key = requests.post(f"{site}/api/pay/key", json={"wallet": acct.address, "signature": sig}).json()["key"]
requests.get(f"{site}/api/pay/refresh", params={"wallet": acct.address})      # after sending TIA/USDC to the treasury
r = requests.get(f"{site}/api/signal/{coin}.json", headers={"Authorization": f"Bearer {key}"})
if r.status_code == 402:
    print("needs credit:", r.json()["pay"])                                   # surface to the operator, do not auto-pay
```

## What we record when you call this

One row per request, so we can tell whether anyone is actually using the API:
the **endpoint family** (not the coin address), a **user-agent class**
(`script`, `browser-direct`, `crawler`, `our-site`, `no-user-agent`), the
country Cloudflare already resolved, the response status, and the first 96
characters of your user-agent so a library can name itself.

No cookie, nothing that identifies an entity. The question we are asking
is "is anyone integrating", not "who". The only per-caller state is the free
allowance counter (keyed by your API key if you send one, else by source IP,
for the current day, discarded after two days) and, if you pay, a credit
balance keyed to your wallet address.

Questions or endpoints you wish existed: open the site and use the feedback
link, or write on-chain — we read the tape.

## Hyperliquid networks: alt.fun and LiquidLaunch (Ansa, 30/10/2026)

Free, no key. Read from the HyperEVM chain every 2 minutes. `{net}` is `altfun` or `liquidlaunch`.

| Endpoint | What it returns |
|---|---|
| `GET /api/hl/status` | each network: up, last block, when we last read it, trades, wallets, volume and new coins in 24h |
| `GET /api/hl/{net}/coins` | every coin: dev, age, trades, buyers, holders, 24h volume, price, market cap, graduated |
| `GET /api/hl/{net}/wallets` | the scoreboard: profit (realised = closed positions only), open, wins, volume, trades |
| `GET /api/hl/{net}/wallet/{address}` | one wallet: P&L, positions, profit by coin, latest 200 trades, its style |
| `GET /api/hl/{net}/coin/{address}` | one coin: holders (top 20 free), bubble map nodes, latest 200 trades |
| `GET /api/hl/{net}/trades?limit=100` | the latest trades (at most 500) |

Paid views (header `x-ansa-pro: 1` with `Authorization: Bearer <key>`): the full trader profile of a wallet and every holder of a coin with the ties between them. One unlock costs 25 reads of paid credit and stays open for 24 hours for that wallet and page. A request without paid credit gets `402` with what to pay.

Names: a wallet shows its `.hl` name when it has set one (HL Names). Otherwise the address.
