API
One call between "the buy is ready" and "sign". No key, no signup. Rate-limited to 30 checks per 10 minutes per IP.
Request
POST /api/check
content-type: application/json
{
"mint": "<token address>",
"amountSol": 0.1,
"intent": "buy 0.1 SOL of an AI coin under $100k, the dev must still hold"
}
intent is the owner's words, read into rules for you. If your agent already has structured limits, send rules instead and no model is involved at all:
{
"mint": "<token address>",
"amountSol": 0.1,
"rules": { "budgetSol": 0.1, "maxMcapUsd": 100000, "devMustHold": true,
"theme": "AI", "themeWords": ["ai", "agent", "gpt"] }
}
Send neither and you get the default safety checks only.
Answer
{
"mint": "…",
"symbol": "EXAMPLE",
"verdict": "ask",
"question": "Before I buy $EXAMPLE: bundlers held 36% of supply at the top. Buy anyway?",
"checks": [
{ "id": "mint", "ok": true, "label": "Nobody can mint more", "detail": "mint authority revoked", "level": "pass" },
{ "id": "bundle", "ok": false, "label": "Not bundled", "detail": "bundlers held 36% of supply at the top", "level": "ask" },
…
],
"rules": { … }
}
ok is true, false, or null when the data isn't there yet. level is what a failed check does: block or ask.
What to do with it: on proceed, sign. On ask, put question to the owner and wait. On block, don't sign.
Rules
| Field | Meaning |
|---|---|
budgetSol | most SOL the agent may spend (blocks above it) |
maxMcapUsd · minMcapUsd | market cap range |
maxAgeMin · minAgeMin | coin age range, minutes |
theme · themeWords | kind of coin, and words to look for in its name, ticker, description and links |
devMustHold | the dev wallet must still hold some |
requireX · minXFollowers | an X account, and how big |
minLiquidityUsd · maxTop10Pct | override the defaults ($2,000 and 40%) |
allowBundled | skip the bundle check |
Examples
curl
curl -s /api/check \
-H 'content-type: application/json' \
-d '{"mint":"<token>","amountSol":0.1,"intent":"an AI coin under $100k"}'
TypeScript, before you sign
const res = await fetch('/api/check', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ mint, amountSol, intent: ownerSaid }),
}).then((r) => r.json());
if (res.verdict === 'block') return; // don't sign
if (res.verdict === 'ask' && !(await owner.confirm(res.question))) return;
await wallet.signAndSend(tx);
Python
r = requests.post("/api/check", json={
"mint": mint, "amountSol": 0.1, "intent": owner_said}).json()
if r["verdict"] == "block": raise SystemExit(r["question"])