Documentation

Apiro API reference

A REST API and MCP server for structural token risk on Robinhood Chain. Authenticate with a bearer token, call one endpoint before you trade, and act on the verdict.

Base URL https://api.apiro.io/v1 Indicative

Overview

Apiro sits between market data and your execution logic. It answers one question in the moments before you commit capital — is this token structurally a trap? — and returns a score, a verdict, itemized flags with reasoning, computed metrics and caveats.

  • REST: four JSON endpoints under /v1.
  • MCP: two tools — assess_token_risk and screen_tokens — for AI agents.
  • Structural, not directional: responses describe exit risk and never predict price.

Pre-launch. Domains, and anything marked indicative, may change before launch. Example responses are abbreviated.

Quickstart

  1. Request an API key.
  2. Score a token you already have an opinion about — the fastest way to calibrate trust in the output.
  3. Add the tradeable gate to one strategy and compare outcomes against your unfiltered baseline.
  4. For agent-based trading, add the MCP endpoint to your configuration alongside your existing trading tools.

Your first request

export APIRO_API_KEY="your_key"

curl "https://api.apiro.io/v1/tokens/0xC7110dd6343fb126865DB673284D5B67F247470F/risk" \
  -H "Authorization: Bearer $APIRO_API_KEY"

Authentication

Every request carries your API key as a bearer token in the Authorization header.

Header
Authorization: Bearer YOUR_KEY

Keep keys server-side: don’t ship them in client-side code or commit them to source control.

Scores & verdicts

Every report has a score from 0 to 100 and a verdict. The score starts at 100; each triggered signal contributes a weighted penalty according to its severity band.

critical< 25
high_risk25–44
caution45–69
acceptable≥ 70

Ranking past the clamp with raw_penalty

The score clamps at zero, but metrics.raw_penalty is the uncapped total, preserving ordering past the clamp. Two tokens can both score 0 while one is substantially worse — sort on raw_penalty for granular ranking below the critical threshold.

A low score is a reason to skip or size down. It is explicitly not a short signal: tokens scored critical sometimes recover, because the score describes exit risk, not price path.

Flags

Each flag describes one structural condition. Flags appear in flags[] on the risk report, and by name in blocking_flags[] on the tradeable gate.

FieldTypeDescription
namestringSignal identifier, e.g. extreme_turnover.
severitystringSeverity band, e.g. moderate, high, severe.
valuenumberThe measured value that triggered the flag.
detailstringPlain-language explanation of what the value means and why it matters. Written to be read by people and reasoning agents.

Signal names

NameMeasures
thin_liquidityPooled USD liquidity across every pool for the token
extreme_turnover24h volume ÷ pooled liquidity
volume_exceeds_mcap24h volume ÷ market capitalisation
newly_launchedHours since the earliest pool was created
price_collapse24h price change
sell_pressureSells as a proportion of all transactions
micro_trade_signatureAverage trade size against transaction count
price_dispersionSpread between the highest and lowest price across pools
activity_cessationLast-hour transactions against the last 24 hours
liquidity_concentrationShare of total liquidity held in a single pool

Thresholds and evidence for each signal

Caveats

Every response includes a caveats array that states the limits of the output in-band, so an agent reasoning over the result weighs it correctly rather than over-trusting it.

caveats
"caveats": [
  "Wash-trading signals are statistical proxies, not proof of intent.",
  "Structural risk only: this score does not predict price direction.",
  "Derived from public DEX pool state; it cannot see contract-level traps."
]

Endpoints

MethodPathPurpose
GET/v1/tokens/{address}/riskFull structural risk report
GET/v1/tokens/{address}/tradeableOne-bit pre-trade gate
POST/v1/tokens/riskBatch scoring, up to 30 addresses
GET/v1/healthLiveness and version

Risk report

GET/v1/tokens/{address}/risk

Full structural risk report: score, verdict, itemized flags with reasoning, computed metrics and caveats.

Path parameters

NameTypeDescription
addressstringToken contract address on Robinhood Chain.

Response fields

FieldTypeDescription
addressstringToken contract address.
symbolstringToken symbol.
scorenumber0–100, clamped at 0.
verdictstringacceptable, caution, high_risk or critical.
flagsobject[]Triggered signals. See Flags.
metricsobjectComputed inputs, including raw_penalty.
caveatsstring[]Limits of the output, returned on every response.

Metrics

FieldDescription
raw_penaltyUncapped penalty total. Sort on it to rank tokens below the clamp.
total_liquidity_usdPooled liquidity across all pools, USD.
volume_h24_usd24-hour volume, USD.
market_cap_usdMarket capitalisation, USD.
turnover_ratio24h volume ÷ pooled liquidity.
volume_to_mcap_ratio24h volume ÷ market cap.
pool_age_hoursHours since the earliest pool was created.
txns_h24Transactions in the last 24 hours.
txns_h1Transactions in the last hour.
avg_trade_size_usdAverage trade size, USD.

Example response

200 · application/json · abbreviated
{
  "address": "0xC7110dd6343fb126865DB673284D5B67F247470F",
  "symbol": "ROBINTWINE",
  "score": 0.0,
  "verdict": "critical",
  "flags": [
    {
      "name": "extreme_turnover",
      "severity": "severe",
      "value": 117.84,
      "detail": "24h volume is 117.8x pooled liquidity. A pool cannot organically recycle its entire depth this many times in a day; this pattern is consistent with wash trading or a small set of wallets cycling the same inventory."
    },
    {
      "name": "volume_exceeds_mcap",
      "severity": "severe",
      "value": 235.19,
      "detail": "24h volume is 235.2x the token's entire market cap ($662.5k traded against a $2.8k cap). Every coin in existence would have to change hands several times over to produce this honestly."
    },
    {
      "name": "activity_cessation",
      "severity": "severe",
      "value": 0,
      "detail": "Zero trades in the last hour against 4,819 over 24h. Activity has stopped dead. Volume that switches off this abruptly was being generated, not demanded -- and with it off there is no bid to exit into at any size."
    }
  ],
  "metrics": {
    "raw_penalty": 158.0,
    "total_liquidity_usd": 5622.15,
    "volume_h24_usd": 662519.47,
    "market_cap_usd": 2817.0,
    "turnover_ratio": 117.84,
    "volume_to_mcap_ratio": 235.19,
    "pool_age_hours": 16.8,
    "txns_h24": 4821,
    "txns_h1": 0,
    "avg_trade_size_usd": 137.42
  },
  "caveats": [
    "Wash-trading signals are statistical proxies, not proof of intent.",
    "Structural risk only: this score does not predict price direction.",
    "Derived from public DEX pool state; it cannot see contract-level traps."
  ]
}

Tradeable gate

GET/v1/tokens/{address}/tradeable

A one-bit gate for bots that want a pre-trade check without parsing a full report.

Parameters

NameInTypeDescription
addresspathstringToken contract address on Robinhood Chain.
min_scorequeryintegerMinimum acceptable score, e.g. 45 — the floor of the caution band.

Response fields

FieldTypeDescription
tradeablebooleanWhether the token passes the gate at your min_score.
scorenumber0–100, clamped at 0.
verdictstringVerdict band for the score.
blocking_flagsstring[]Names of the flags that blocked the trade.
reasonstringPlain-language reason the gate closed.
address, symbolstringAs in the risk report.

Example

curl "https://api.apiro.io/v1/tokens/0xC7110dd6343fb126865DB673284D5B67F247470F/tradeable?min_score=45" \
  -H "Authorization: Bearer $APIRO_API_KEY"
200 · application/json · abbreviated
{
  "address": "0xC7110dd6343fb126865DB673284D5B67F247470F",
  "symbol": "ROBINTWINE",
  "tradeable": false,
  "score": 0.0,
  "verdict": "critical",
  "blocking_flags": ["thin_liquidity", "extreme_turnover", "volume_exceeds_mcap"],
  "reason": "Total pooled liquidity is $5.6k..."
}

Batch scoring

POST/v1/tokens/riskIndicative body

Batch scoring for screening candidate sets — up to 30 addresses per call.

Request body

FieldTypeDescription
addressesstring[]Token addresses to score. Maximum 30 per call.

Example

curl -X POST "https://api.apiro.io/v1/tokens/risk" \
  -H "Authorization: Bearer $APIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"addresses": ["0xC7110dd6343fb126865DB673284D5B67F247470F"]}'

The batch request and response shapes will be confirmed at launch. For agents, screen_tokens returns candidates ranked safest-first with blocking flags.

Health

GET/v1/health

Liveness and version — use it for uptime checks and deployment verification.

health.sh
curl "https://api.apiro.io/v1/health" \
  -H "Authorization: Bearer $APIRO_API_KEY"

Rule-based bots

One call, one branch, placed immediately before order submission.

pre_trade.py
import httpx

def should_trade(address: str, min_score: int = 45) -> bool:
    r = httpx.get(
        f"https://api.apiro.io/v1/tokens/{address}/tradeable",
        params={"min_score": min_score},
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=2.0,
    )
    return r.json()["tradeable"]

if should_trade(token_address):
    execute_buy(token_address, size)

Because the underlying signals move slowly, responses are safely cacheable for a minute or more — so the gate adds negligible latency to a hot path and negligible cost to a high-frequency strategy.

With a cache and an explicit failure mode

pre_trade_cached.py
import time
import httpx

TTL_SECONDS = 60
_cache: dict[tuple[str, int], tuple[float, bool]] = {}

def should_trade(address: str, min_score: int = 45) -> bool:
    key = (address, min_score)
    hit = _cache.get(key)
    if hit and time.monotonic() - hit[0] < TTL_SECONDS:
        return hit[1]
    try:
        r = httpx.get(
            f"https://api.apiro.io/v1/tokens/{address}/tradeable",
            params={"min_score": min_score},
            headers={"Authorization": f"Bearer {API_KEY}"},
            timeout=2.0,
        )
        r.raise_for_status()
        tradeable = r.json()["tradeable"]
    except httpx.HTTPError:
        return False  # fail closed: no check, no trade
    _cache[key] = (time.monotonic(), tradeable)
    return tradeable

MCP for AI agents

Apiro ships as an MCP (Model Context Protocol) server, so it drops into the same configuration as your agent’s trading tools — for example alongside Robinhood’s Agentic Trading, which connects third-party AI agents to a dedicated brokerage account over MCP. The agent holds both the ability to trade and the ability to check what it’s about to trade.

MCP configurationIndicative URL
{
  "mcpServers": {
    "apiro": {
      "url": "https://mcp.apiro.io/sse",
      "headers": { "Authorization": "Bearer YOUR_KEY" }
    }
  }
}

Tools

ToolUse it to
assess_token_riskGet a structural assessment of one token before trading it.
screen_tokensChoose between up to 30 candidates, returned ranked safest-first with blocking flags.

Why agents get more out of it

A rule-based bot can only threshold on a number; everything qualitative in the response is wasted on it. An agent reads “the deployer’s pool is sixteen hours old, volume is 235× the entire market cap, and trading stopped an hour ago” and weighs it against the user’s instructions — perhaps proceeding at reduced size on a token scored 50, and refusing outright on one scored 20, without anyone hard-coding either threshold.

Screening pipelines

For strategies that generate candidate sets — new-launch monitors, trending scans — batch scoring filters the set before any deeper analysis runs, removing the majority of candidates at a fraction of the cost of evaluating them individually.

  • Score candidates in batches of up to 30.
  • Drop anything below your min_score before running expensive analysis.
  • Rank what remains below the critical threshold by raw_penalty.

Caching & latency

Apiro recomputes on a cadence of minutes, not milliseconds. Structural conditions move slowly, so being a few seconds behind costs nothing — and Apiro stays out of the latency arms race entirely.

  • Cache responses for a minute or more.
  • Use a short client timeout — the examples use two seconds — and decide explicitly what happens when a check fails.
  • Prefer batch scoring for candidate sets over many single calls.
  • Rate limits depend on your tier — see pricing.

Limitations

  • Structural risk only. Scores don’t predict price direction.
  • Statistical proxies. Manufactured-volume signals are patterns, not proof of intent.
  • Pool state only. Contract-level traps — mint authority, transfer blacklists, honeypot logic, proxy upgradeability — aren’t visible yet.

Planned: contract-level risk analysis, a deployer reputation graph, wallet clustering, listing-catalyst intelligence, a historical scoring API and webhooks. See the roadmap.