Hunter KillerCreate free account
Menu

For AI agents.

If you are an agent: this page is your map: every path below is live, keyless, and returns JSON you can verify. If you are building with agents: liquidation intelligence with a public record where every level we publish goes on the record, misses included, each figure with its sample size and a Wilson 95% lower confidence bound, plus a falsification record we publish, including the symbols we switched off.

Descriptive measurements of past performance. Never a forecast, never financial advice.

Try it now

One call returns BTC liquidation walls, snapshot age, evidence labels and the public record. Free data is 2 hours behind on six coins. No key or card.

curl --fail-with-body --max-time 20 https://hunterkiller.io/api/v1/levels/BTCUSDT

Press the button to make one API call. There are no background calls.

The response will appear here.

Keep the delay, age and evidence labels with any result you show. Descriptive measurements, not trading advice. Agent examples and tools. Public record.

BotsFor trading bots and Telegram trading groups

One call per coin returns the liquidation walls a bot needs: the nearest wall above and below the mark, every wall with its dollar size, signed distance, age and evidence label, the snapshot time, and a link to the public record. The numbers are the ones the dashboard shows at the same snapshot.

GET /api/v1/levels/{symbol}

Free key: a 2 hour delayed snapshot on the Free coins, 60 calls per minute, metered per key. Sign in, then call POST /api/keys/free.

Bot API key

$49 a month or $470 a year. Founding price locked for the first 50 subscribers.

The current snapshot on every covered coin, 120 calls a minute, 100,000 calls a month and the public record link.

Start monthly, $49 Start yearly, $470

Sign in first, then mint your key with POST /api/keys/mine. A free key stays free.

Authorization: Bearer hk_live_...

Real time: a Bot API key, an API plan key, a Pro session, prepaid credits on any key (from $10 for 600 calls), or x402 at $0.005 per call in USDC on Base.

What each call returns

Copy-paste examples

Python

import os, requests  # pip install requests

KEY = os.environ["HK_API_KEY"]  # free key: sign in, then POST /api/keys/free
res = requests.get("https://hunterkiller.io/api/v1/levels/BTCUSDT",
                   headers={"Authorization": "Bearer " + KEY}, timeout=10)
res.raise_for_status()                    # 401 no key, 403 coin needs paid access, 429 slow down
lv = res.json()
print(lv["symbol"], lv["mark"]["price"], lv["tier"], lv["as_of_iso"], "age", lv["age_sec"], "s")
for name in ("above", "below"):
    w = lv["nearest"][name]
    if w:
        print(name, w["price"], w["distance_label"], f"${w['usd']:,.0f}", w["evidence"])

Node

// Node 18+ (built-in fetch)
const key = process.env.HK_API_KEY;
const res = await fetch("https://hunterkiller.io/api/v1/levels/BTCUSDT", {
  headers: { Authorization: `Bearer ${key}` },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const lv = await res.json();
console.log(lv.symbol, lv.mark.price, lv.tier, lv.as_of_iso, "age", lv.age_sec, "s");
for (const [name, w] of Object.entries({ above: lv.nearest.above, below: lv.nearest.below })) {
  if (w) console.log(name, w.price, w.distance_label, Math.round(w.usd), w.evidence);
}

curl

# one coin
curl -s -H "Authorization: Bearer $HK_API_KEY" https://hunterkiller.io/api/v1/levels/BTCUSDT
# up to 10 coins in one request, metered one call per coin
curl -s -H "Authorization: Bearer $HK_API_KEY" "https://hunterkiller.io/api/v1/levels?symbols=BTCUSDT,ETHUSDT,SOLUSDT"
# your metered calls today
curl -s -H "Authorization: Bearer $HK_API_KEY" https://hunterkiller.io/api/v1/levels/usage
# keyless: the x402 price quote (402), then pay per call in USDC on Base
curl -s "https://hunterkiller.io/api/v1/levels/BTCUSDT?live=1"

Freqtrade: skip an entry when a big wall sits between price and your target. The same check fits a Hummingbot script or a 3Commas webhook relay.

# In your strategy under user_data/strategies: add confirm_trade_entry to your IStrategy
import os, time, requests
from freqtrade.strategy import IStrategy

HK = "https://hunterkiller.io/api/v1/levels/"
HEAD = {"Authorization": "Bearer " + os.environ["HK_API_KEY"]}
MAX_WALL_PCT, MIN_WALL_USD = 1.5, 50e6   # your rule: tune both
_cache = {}

def hk_levels(pair):
    sym = pair.split("/")[0] + "USDT"      # "BTC/USDT:USDT" becomes "BTCUSDT"
    hit = _cache.get(sym)
    if hit and time.time() - hit[0] < 60:  # one call per coin per minute is plenty
        return hit[1]
    lv = requests.get(HK + sym, headers=HEAD, timeout=5).json()
    _cache[sym] = (time.time(), lv)
    return lv

class WallAwareStrategy(IStrategy):
    # ... your populate_indicators / populate_entry_trend / populate_exit_trend ...
    def confirm_trade_entry(self, pair, order_type, amount, rate, time_in_force,
                            current_time, entry_tag, side, **kwargs) -> bool:
        try:
            lv = hk_levels(pair)
        except Exception:
            return True                    # data unavailable: never block on us
        if not lv.get("ok"):
            return True
        wall = lv["nearest"]["above" if side == "long" else "below"]
        if wall and abs(wall["distance_pct"]) < MAX_WALL_PCT and wall["usd"] > MIN_WALL_USD:
            return False                   # a big wall sits between price and the target
        return True

Prop desk data sheet. Fields, cadence, history depth and the public record on one page. OpenAPI 3.0 · /api/v1/levels/symbols

GET /api/v1/levels/usage shows your key's metered calls today.

Modeled levels. Descriptive, not a forecast and not a trade instruction. Nothing here places an order.

01Discovery artifacts

Start here: each file is generated from the same endpoint registry, so they can never disagree:

/agents.json

The capability manifest: every public endpoint with method, auth tier, rate limit, params and response fields, plus the MCP block and the auth/pricing surfaces.

/llms.txt · /llms-full.txt

The concise index and the extended version: per-endpoint params, response fields, curl examples, honesty caveats.

/.well-known/mcp.json

Streamable-HTTP MCP discovery document: server info, protocol versions, and the tool list with per-tool access tiers.

/developers/openapi.json

OpenAPI 3.0 spec for the free endpoints, generated from the same registry with live rate limits in every operation.

StartBefore a trade, call the Desk Read FREE DELAYEDLIVE WITH A KEY OR x402

Copy-paste configs

Claude Code:

claude mcp add --transport http hunterkiller https://hunterkiller.io/mcp

Claude Desktop or Cursor (claude_desktop_config.json or .cursor/mcp.json):

{
  "mcpServers": {
    "hunterkiller": { "url": "https://hunterkiller.io/mcp" }
  }
}

OpenAI function calling. The same schema is served at GET /agents/tools.openai.json:

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "desk_read",
        "description": "Call before placing a leveraged perp order. Returns where liquidation money is stacked, where your position would be taken out, how far a cascade runs, who is paying funding, and a descriptive verdict (wall_in_band, no_wall_in_band or thin_data) with stop and target suggestions. Free delayed data without a key. Descriptive, not a forecast.",
        "parameters": {
          "type": "object",
          "properties": {
            "symbol": {
              "type": "string",
              "description": "Perp pair, e.g. BTCUSDT. See GET /api/desk_read/symbols."
            },
            "side": {
              "type": "string",
              "enum": [
                "long",
                "short"
              ],
              "description": "Your position side."
            },
            "entry": {
              "type": "number",
              "description": "Your entry price."
            },
            "leverage": {
              "type": "number",
              "description": "Your leverage, e.g. 20."
            },
            "ref": {
              "type": "string",
              "description": "Your agent name, for attribution."
            }
          },
          "required": [
            "symbol"
          ],
          "additionalProperties": false
        }
      }
    }
  ]
}

Python: call the Desk Read before an order and skip when liquidation is too close.

import json, os, urllib.error, urllib.request
MIN_DISTANCE_PCT = 6.0  # skip when liquidation is closer than this

def desk_read(sym, side, entry, lev):
    url = (f"https://hunterkiller.io/api/desk_read?symbol={sym}&side={side}"
           f"&entry={entry}&leverage={lev}&ref=my-agent")
    req = urllib.request.Request(url)
    if os.environ.get("HK_API_KEY"):
        req.add_header("Authorization", "Bearer " + os.environ["HK_API_KEY"])
    return json.load(urllib.request.urlopen(req, timeout=10))

def place_order(sym, side, entry, lev):
    ...  # your exchange call

for sym, side, entry, lev in [("BTCUSDT", "long", 81000, 20)]:
    try:
        read = desk_read(sym, side, entry, lev)
    except urllib.error.HTTPError as e:   # 404 unknown_symbol, 422 invalid_number
        print("no trade, desk read refused:", e.read().decode()); continue
    hurt = read["hurt"]
    if hurt is None or hurt["distance_pct"] < MIN_DISTANCE_PCT:
        print("skip", sym, read["hurt_reason"] or read["text"]); continue
    print(read["verdict"], read["text"])
    place_order(sym, side, entry, lev)

TypeScript: the same loop.

const MIN_DISTANCE_PCT = 6; // skip when liquidation is closer than this
const key = process.env.HK_API_KEY;

async function deskRead(sym: string, side: string, entry: number, lev: number) {
  const url = `https://hunterkiller.io/api/desk_read?symbol=${sym}&side=${side}` +
    `&entry=${entry}&leverage=${lev}&ref=my-agent`;
  const res = await fetch(url, { headers: key ? { Authorization: `Bearer ${key}` } : {} });
  if (!res.ok) throw new Error(await res.text()); // 404 unknown_symbol, 422 invalid_number
  return res.json();
}

async function placeOrder(sym: string, side: string, entry: number, lev: number) {
  // your exchange call
}

for (const [sym, side, entry, lev] of [["BTCUSDT", "long", 81000, 20]] as const) {
  const read = await deskRead(sym, side, entry, lev).catch((e) => (console.log("no trade:", String(e)), null));
  if (!read) continue;
  if (!read.hurt || read.hurt.distance_pct < MIN_DISTANCE_PCT) {
    console.log("skip", sym, read.hurt_reason ?? read.text); continue;
  }
  console.log(read.verdict, read.text);
  await placeOrder(sym, side, entry, lev);
}

Python SDK: pip install hunterkiller, then desk_read(), watch() (a stream that tells you when a wall comes into range) and symbols(). Source in the public SDK repo.

TypeScript SDK: npm install hunterkiller-sdk, then deskRead(), watch() and symbols(). Same repo.

Specs: OpenAPI 3.0 · Postman collection · covered symbols: /api/desk_read/symbols.

One call, five plain-word answers for a perp pair, plus lines[] and a ready-to-send text block. REST: GET /api/desk_read?symbol=BTCUSDT (optional side, entry, leverage, ref). MCP tool: desk_read on /mcp. An agent that pays per call is a subscriber.

Pay with a card. Prepaid packs from $10, bought with a card, 600 live calls. Any API key holder, a free key included, can buy one: POST /api/agents/credits/checkout with {"pack_id": "p10"} (also p50, p200) returns a Stripe Checkout URL, or call the MCP tool buy_credits and hand the URL to your human. GET /api/agents/credits shows the balance. With credits a keyed Desk Read is live and spends one credit per request (one per watch event); X-HK-Credits-Remaining shows what is left, and at zero the call falls back to the key's normal tier. Packs: $10 for 600 calls, $50 for 3,500, $200 for 16,000. x402 stays available next to it; the x402 Bazaar listing appears after the first settled payment.

Free vs paid. A keyless call is free and gets the delayed tier. A B2B API key (Authorization: Bearer <key> or x-api-key), a Pro session, or an x402 payment gets live data. Add live=1 with no payment to receive the 402 price quote (default $0.02 USDC on Base per call; the live price is in the 402 response and in access.price_usd_per_live_call). The x402 client flow is the one in examples/first-purchase. Rate limits. Keyless REST shares the global per-IP limiter quoted at /developers; keyless MCP is capped at 10 tool calls per minute per IP; keyed calls follow your key's plan limits. Over the limit returns 429 with Retry-After. Add ref=your-agent-name so we can see which agents use it. Descriptive, not a forecast.

curl -s "https://hunterkiller.io/api/desk_read?symbol=BTCUSDT&side=long&entry=81000&leverage=20&ref=my-agent"
import json, os, urllib.request
url = "https://hunterkiller.io/api/desk_read?symbol=BTCUSDT&side=long&entry=81000&leverage=20&ref=my-agent"
req = urllib.request.Request(url)
if os.environ.get("HK_API_KEY"):
    req.add_header("Authorization", "Bearer " + os.environ["HK_API_KEY"])
read = json.load(urllib.request.urlopen(req))
print(read["text"])
const key = process.env.HK_API_KEY;
const res = await fetch(
  "https://hunterkiller.io/api/desk_read?symbol=BTCUSDT&side=long&entry=81000&leverage=20&ref=my-agent",
  { headers: key ? { Authorization: `Bearer ${key}` } : {} },
);
const read = await res.json();
console.log(read.text);

Machine fields

Why a section is null

When hurt or plan is null, hurt_reason or plan_reason says why. Three values:

Errors and headers

Bad input fails loudly. An unknown symbol returns 404 {"error":"unknown_symbol","symbol":"FOO","did_you_mean":[...],"symbols_url":"/api/desk_read/symbols"}. A non-numeric entry or leverage returns 422 {"error":"invalid_number","field":"entry"}. The MCP tool returns the same payload with isError: true. A bare base like BTC is accepted as BTCUSDT only because that pair is covered; FOO is never rewritten to FOOUSDT. List what is covered with GET /api/desk_read/symbols (free and live tiers, the free-tier delay, cached 5 minutes). Responses carry RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset from the limiter that served you, Cache-Control: public, max-age=20 on the free tier and private, no-store on live, and X-HK-Data-Age-Seconds. The 402 body adds message and docs; the x402 headers are unchanged.

02Free REST endpoints KEYLESS

No key, no signup. The delayed cross-exchange liquidation tape and the full measured track record, as public JSON. Full docs with params and response fields: /developers.

GET /api/public/liq_teaser

Cross-exchange liquidation tape, majors only, delayed on the free tier. 24h totals + last 40 events ≥ $5k.

GET /api/public/coin_teaser/{symbol}

Per-coin liquidation snapshot for any tracked perp symbol (BTCUSDT, ETHUSDT, …). Unknown symbols 404 honestly.

GET /proof/stats

The public record: every level we publish goes on the record, misses included. Released counts and dates, each with n and a Wilson 95% lower bound.

GET /proof/evidence · /proof/ledger.csv

The complete published ledger, including auto-disabled symbols. Publishing what we switched off is the point.

GET /proof/anchors

Daily cryptographic hash anchors over the proof artifacts. Verify the ledger's integrity independently.

GET /proof/feed_trust · /feeds/trust

Per-venue reconciliation verdicts on our own tape, against independent exchange references, with n shown.

curl -s https://hunterkiller.io/api/public/liq_teaser
curl -s https://hunterkiller.io/proof/stats

03MCP server 3 FREE TOOLSDATA TOOLS NEED A KEY

Find the managed OAuth server in the official MCP Registry or on MCP.so.

One streamable-HTTP endpoint at /mcp, stateless: a single JSON-RPC 2.0 request per POST, JSON response. Keyless clients get protocol discovery plus three free tools (get_proof_summary, get_feed_trust_summary, get_magnet_levels_teaser) built only from surfaces the public website already publishes. The graded data tools (calibrated magnets, reach stats, …) require a B2B API key, metered identically to the REST /api/v1 API.

# 1. initialize (once per client)
curl -s -X POST https://hunterkiller.io/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0"}}}'

# 2. list the tools
curl -s -X POST https://hunterkiller.io/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# 3. call a free tool (no key)
curl -s -X POST https://hunterkiller.io/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_proof_summary","arguments":{}}}'

Discovery first: GET /.well-known/mcp.json: protocol versions, server info, and the tool list with per-tool tiers.

04Proof discipline

Every number carries its evidence. Accuracy is measured on historical data, de-overlapped, and every figure ships with its sample size n and a Wilson 95% lower confidence bound. Unvalidated horizons are withheld, never served as numbers. The ledger includes symbols we auto-disabled. The feed-trust audit grades our own tape against independent venue references. The anchor chain lets you verify the ledger's integrity cryptographically; /proof/anchors documents how.

05Rate limits

06Get an API key

The paid B2B Data API (/api/v1/*) requires an API key (Authorization: Bearer <key> or x-api-key), is metered, and serves real-time data across the full tracked universe: the same validated data layer the MCP data tools use. Sign up at /signup; key self-management lives at /api/keys/mine (login required). Docs: /docs. Pricing: /pricing.

07Machine payments (agents) NO LOGIN

An autonomous agent cannot do an email signup or a checkout page, so it does not have to. Two machine rails, same USDC on Base, both honest about their own state (an unconfigured rail says dormant and advertises nothing):

# terms are served live (dormant until the receiving address is published)
curl -s https://hunterkiller.io/agents.json | jq '.pricing.machine, .pricing.machine.x402'

# balance rail, after paying USDC on Base to pricing.machine.pay_to:
curl -X POST https://hunterkiller.io/api/payg/agent_bootstrap \
  -H 'content-type: application/json' \
  -d '{"tx_hash": "0x..."}'
# -> {"api_key": "hk_...", "credited_usd": ...}  (the key is shown ONCE)

# x402 per-call rail: any x402 client library handles the 402 -> sign -> retry flow
# (pip install x402 / @x402/fetch) against https://hunterkiller.io/api/v1/magnets

# Coinbase Payments MCP (agents.coinbase.com/mcp, npx @coinbase/payments-mcp):
# its wallet speaks x402 on Base USDC, so these endpoints are payable by it out
# of the box; the agent sees the 402 requirements and pays, no API key, no signup

Compatible wallets: any x402-capable agent wallet, including Coinbase's Payments MCP (agents.coinbase.com/mcp, npx @coinbase/payments-mcp). The per-call requirements above are standard x402 on Base USDC, so a Payments-MCP agent pays without keys or account setup. On-chain verification: contract, 2+ confirmations, amount floor, replay-guarded. A payment that does not verify is never credited. Rate limits: institutional keys 120/min, pay-as-you-go 30/min, x402 per-call settles at chain speed.

08The honesty contract

Read this before you wire us into a decision loop. Everything we serve is a descriptive measurement of past performance, delayed on the free tier by design, sampled with n shown, bounded with Wilson confidence intervals. It is not a forecast, not a signal feed, and not financial advice. Free tape delay is real: you are looking at the past, on purpose. If a number can't meet the disclosure bar, we don't serve it.

Terms · Privacy · Risk disclosure