TonWise API

Real-time on-chain security layer for TON. Detect Puppet Masters, Sybil clusters and Unicode spoofs before your users lose money.

<50ms Shield latency
10+ Threats caught/week
7,500+ Graph nodes
24/7 Auto-Hunter
ℹ️ All endpoints require an X-API-Key header. Get one instantly with USDT at tonguard.app/pricing, or contact @TonWiseDev.

Authentication

Pass your API key in the X-API-Key header on every request.

curl
curl https://tonguard.app/api/v1/shield \
  -H "X-API-Key: tw_live_your_key_here" \
  -G -d "contract=EQBHNioKtx8Fu3pglkxSzvl9zt4KY1ixUl0miMSVCyHvDW60"

Rate Limits

Shield API responses are Redis-cached. Cache miss triggers live blockchain analysis (~2-5s). Cache hit returns in <50ms.

PlanLimitCache TTL
Free60 req/min per key24h
Pro1,000 req/min per key24h
EnterpriseUnlimitedConfigurable
⚠️ Rate limit headers are returned on every response: X-RateLimit-Limit and X-RateLimit-Remaining

Pre-trade Contract Screening

Run a contract through TonWise before a trade executes. Returns risk score, dump probability and sybil cluster count. Cached responses return in under 50ms.

GET /api/v1/shield Fast-lane B2B screening

Query Parameters

ParameterTypeRequiredDescription
contract string required TON contract address (EQ... or 0:...)

Example Request

curl
curl "https://tonguard.app/api/v1/shield?contract=EQBHNioKtx8Fu3pglkxSzvl9zt4KY1ixUl0miMSVCyHvDW60" \
  -H "X-API-Key: tw_live_your_key"

Response

json
{
  "contract":         "EQBHNioKtx8Fu3pglkxSzvl9zt4KY1ixUl0miMSVCyHvDW60",
  "is_safe":          false,
  "dump_probability": 44,
  "reason":           "SYBIL_CONCENTRATION_DETECTED",
  "sybil_clusters":   2
}

Numeric fields (dump_probability, sybil_clusters) are computed live and vary over time; is_safe and reason are the stable signal.

Reason Codes

ReasonDescription
CLEANNo threats detected
SYBIL_CONCENTRATION_DETECTEDPuppet Master + Sybil cluster found
DUMP_IMMINENTMicro test-transactions detected, sell incoming
CROSS_CHAIN_EXIT_*Liquidity draining via bridge
INVALID_CONTRACT_OR_NO_HOLDERSContract not found or empty
UPSTREAM_DEGRADEDData source temporarily unavailable — retry in a few minutes (degraded ≠ clean)

Stablecoin Freeze & Taint Screening

Check any address for a direct issuer freeze (Tether / Circle / OFAC) or proximity to frozen funds (contagion). Covers USDT & USDC on Ethereum, Tron and TON. Cached responses return in under 50ms.

GET /api/v1/freeze/{address} Freeze + contagion check

Parameters

ParameterTypeRequiredDescription
address string (path) required Address to screen (TON EQ.../UQ..., ETH/TRON 0x...)
chain string (query) required One of TON, ETH, TRON

Example Request

curl
curl "https://tonguard.app/api/v1/freeze/0xd90e2f925da726b50c4ed8d0fb90ad053324f31b?chain=ETH" \
  -H "X-API-Key: tw_live_your_key"

Response

json
{
  "address":            "0xd90e2f92...324f31b",
  "chain":              "ETH",
  "direct_freeze":      true,
  "freeze_issuer":      "Circle",
  "contagion_risk":     "CRITICAL",
  "freeze_probability": 100,
  "recommendation":     "Do NOT transact. Funds are frozen.",
  "data_fresh":         true,
  "is_risky":          true
}

Contagion Risk Levels

LevelDescription
CLEANNo direct freeze or proximity to frozen funds
LOW / MEDIUMIndirect exposure several hops from frozen funds
HIGHClose to frozen funds — elevated future-freeze risk
CRITICALDirectly frozen or one hop away — do not transact
Fail-closed: every response carries data_fresh. If the freeze index is stale the API errs toward caution instead of returning a false "clean".

Autonomous Agent Decision API

Real-time ALLOW / REVIEW / BLOCK decisions for autonomous AI agents executing on-chain operations. Per-agent anomaly detection, idempotent under retry, HMAC-signed audit receipts. Designed for wallet SDKs, agent frameworks, MEV bots — any system where a non-human signs transactions.

Tier: Pro or above required. Free keys receive HTTP 403 with a current_tier field for graceful upgrade prompts.
POST /api/v1/agent-guard Evaluate one agent intent

Request Body (JSON)

FieldTypeRequiredDescription
target_contract string required TON contract address the agent intends to interact with
intent enum optional One of swap, send, stake, other. Default: other
agent_id string optional Stable identifier for the agent — required for anomaly scoring to engage
agent_wallet string optional Agent's signing wallet address
target_wallet string optional For send/transfer intents, the destination wallet
value_ton number optional TON amount being moved
value_usd_estimated number optional USD-equivalent estimate — feeds anomaly baseline
max_acceptable_risk number optional Float in [0.0, 1.0]. When exceeded, decision tilts toward BLOCK
context string optional Free-form context (max 512 chars) — what the agent is trying to accomplish
⚠️ Send an Idempotency-Key header (UUID4) to safely retry. Duplicate keys within 24h return the original cached decision with X-Idempotent-Replayed: true. The same key reused with a different request body returns 422 (collision).

Example Request

curl
curl -X POST "https://tonguard.app/api/v1/agent-guard" \
  -H "X-API-Key: tw_live_your_pro_key" \
  -H "Idempotency-Key: f5a7c123-7c08-4d9b-bd29-9ba1d0c84e10" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id":            "my-mev-bot-01",
    "intent":              "swap",
    "target_contract":     "EQAc2DO-7EOnVAv985EL-RhpW_9l5DmhYLjCrd02IsyNvDzb",
    "value_usd_estimated": 250,
    "context":             "Trending token from social feed"
  }'

Response

json
{
  "telemetry_id":    "tg_AGT_ecad5004",
  "decision":        "BLOCK",
  "confidence":      0.91,
  "risks": [
    {"code": "SYBIL_CONCENTRATION", "severity": "critical"}
  ],
  "reasoning":       "3 sybils controlled by 1 master ...",
  "alternatives":    [{"contract": "EQCxE6mU...", "reason": "Native USDT on TON"}],
  "computed_at":     "2026-05-14T11:52:10Z",
  "ttl_seconds":     3600,
  "latency_ms":      147,
  "audit_signature": "a3f8b1...c4d1e2",
  "signing_key_id":  "key_2026_q2"
}

Decision Values

DecisionMeaning
ALLOWSafe to proceed. Agent may execute the intent.
REVIEWSuspicious. Agent should pause, request human confirmation, or fall back to a safer alternative.
BLOCKStrong evidence of fraud. Agent must abort the intent.

Audit Signature

Every decision is signed with HMAC-SHA256 over a canonical 5-field string (telemetry_id, decision, target_contract, value_usd, computed_at). Verify offline in any language — see the verification recipe. Closes the trust loop: clients save the signature on POST, anyone can later confirm authenticity via POST /api/v1/audit/verify without DB access or PII exposure.

POST /api/v1/agent-guard/{telemetry_id}/outcome Postmortem feedback

Report what actually happened after a decision was acted on. Feeds precision/recall metrics and improves the model over time. Pro tier or above. Idempotent per telemetry_id.

Request Body (JSON)

FieldTypeRequiredDescription
actual_outcome enum required One of success, loss, missed_opportunity
loss_usd number optional USD value lost when actual_outcome=loss. Used in daily $-saved aggregation.
notes string optional Free-form context (max 512 chars)
GET /api/v1/agent-guard/metrics?window=7 Decision quality snapshot

Daily precision, recall, and dollar-saved time-series for your own decisions. Pro tier or above. Tenant-isolated — every caller sees only their own data; any ?client=... query parameter is ignored on the server side.

Query Parameters

ParameterTypeDescription
windowintegerDays back to include. Accepted values: 7 or 30.
GET /api/v1/agent-guard/{telemetry_id} Public verification card

Sanitized decision lookup with the original signature. No authentication required — anyone with a telemetry_id can verify that the decision was actually made. Per-IP rate limited (60/min, fail-open). Useful for embedding "verified by TonWise" badges in agent UI or post-mortem reports.

Path Parameters

ParameterTypeDescription
telemetry_idstringDecision identifier returned from POST /api/v1/agent-guard

Address Cluster Intelligence

Map the full scammer cluster around any TON address through the Lazarus graph. BFS-traversal at depth 3 returns linked scams, threat score, cluster membership, and (when available) cross-chain exit history. Where Shield scans one token, Threat Intel maps the network behind it.

Tier: Pro or above required ($99+/mo). Free and Starter keys receive HTTP 403 with current_tier field for graceful upgrade prompts.
GET /api/v1/threat-intel/{address} Aggregated graph intel

Path Parameters

ParameterTypeRequiredDescription
address string required TON address. Accepts user-friendly (EQ.../UQ...) or raw (0:hex) format — server canonicalizes on input.

Example Request

curl
curl "https://tonguard.app/api/v1/threat-intel/EQDa4VOnTYlLvDJ0gZjNYm5PXfSmmtL6Vs6A_CZEtXCNICq_" \
  -H "X-API-Key: tw_live_your_business_key"

Python SDK

python
from tonwise import TonWiseClient, TierError

with TonWiseClient(api_key="tw_live_your_business_key") as client:
    try:
        intel = client.threat_intel("EQDa4VOnTYlLvDJ0gZjNYm5PXfSmmtL6Vs6A_CZEtXCNICq_")
        print(f"Threat score: {intel.threat_score}/100")
        for scam in intel.linked_scams:
            print(f"  → {scam.contract} ({scam.symbol})")
    except TierError as e:
        print(f"Need Business tier, you have: {e.current_tier}")

SDK: pip install tonwise (≥ 0.2.0). Both sync (TonWiseClient) and async (AsyncTonWiseClient) variants expose threat_intel(address).

Response (200)

json
{
  "address":                  "0:dae153a74d894bbc32748198cd626e4f5df4a69ad2fa56ce80fc2644b5708d20",
  "threat_score":             40,
  "first_seen":               null,
  "last_activity":            null,
  "associated_addresses":     4999,
  "linked_scams": [
    {
      "contract":    "0:6e6d431b9bafe1...",
      "symbol":      "SYBIL",
      "first_seen":  null,
      "labels":      ["SCAM", "flagged"]
    }
  ],
  "puppet_master_cluster_id": null,
  "labels":                   ["SCAM", "PUPPET_MASTER"],
  "cross_chain_exits":        [],
  "graph_depth":              3,
  "computed_at":              "2026-05-10T12:00:00.000Z"
}

Response Fields

FieldTypeDescription
addressstringCanonical raw form (0:hex), regardless of input format. Echo for client-side cache keying.
threat_scoreint 0-100Nonlinear function of bad-edge density in the cluster. 0 = clean, 100 = saturated with flagged neighbors. Use ≥70 as a hard-block threshold.
associated_addressesintTotal nodes visited in BFS (excluding the queried address). Capped at 5000 for predictable latency.
linked_scams[]arrayTop 20 flagged neighbors, BFS-ordered by proximity (closest first).
linked_scams[].symbol string Threat label (e.g. "SYBIL", "Scam/Risk", "Phishing") — not a jetton symbol. Reflects how the address is classified in the threat graph, sourced from node.label in Lazarus.
labels[]arrayTags on the queried address itself, present only if it's flagged. Common values: "SCAM", "PUPPET_MASTER", "PHISHING".
puppet_master_cluster_idstring?Cluster ID if address belongs to a known Sybil cluster. Currently always null; populated as Lazarus clustering API expands.
cross_chain_exits[]arrayBridge exit history. Currently always empty; populated when KNOWN_INFRASTRUCTURE mapping ships in a future release.
first_seen / last_activitystring?Per-address timestamps. Currently always null; planned for the next graph-layer iteration.
graph_depthintBFS depth used (currently fixed at 3).
computed_atstringISO-8601 UTC timestamp of computation.

Tier Gate Response (403)

Pro or Free keys receive a 403 with the current_tier field — distinguishable from invalid-key 403 (which has no current_tier):

json
{
  "error":        "Threat Intel API requires Business or Enterprise tier",
  "current_tier": "pro"
}

The Python SDK maps this to tonwise.TierError (subclass of TonWiseError) with .current_tier attribute.

Caching & Latency

Responses cached in Redis for 1 hour with distributed-lock protection against thundering herd on cold cache. Warm latency under 50ms; cold BFS computation typically 60-150ms depending on cluster density. The cluster cap at 5000 visited nodes keeps cold latency predictable for high-traffic addresses.

Shareable Threat Artifacts

Every Auto-Hunter catch is automatically materialized as a public receipt page at tonguard.app/r/{id}. Receipts are pre-rendered with Open Graph and Twitter Card meta tags — any link share (Twitter, Telegram, Discord, Slack, iMessage) surfaces a rich preview with severity badge, threat ID, and key stats.

Free. No API key required. Pages are public and indexable. They exist to make TonWise's value visible whenever a flagged contract gets discussed anywhere on the web.

How Receipts Are Created

The Auto-Hunter monitors new TON liquidity pools and flags scams in real time — Sybil clusters, dump-imminent setups, Unicode-spoof tokens. Each catch triggers two simultaneous actions:

  • A threat report is published to @tonwise_intel Telegram channel.
  • A persistent Receipt row is written to the database with severity, threat ID, sybil count, AI analysis, and a stable 8-hex ID (e.g. r_f698cc17).

The receipt URL is appended to the channel post. Subscribers get a one-tap shareable link; outsiders following the link land on a full threat-detail page.

Receipt Page Anatomy

ElementDescription
Severity badgeCRITICAL / HIGH / MEDIUM / LOW with color-coded border. Severity is floored at MEDIUM for any receipt that came from a publish-gated alert.
Threat IDStable identifier in TW-YYYY-XXXX format. Same contract gets the same ID within a calendar year.
Stats gridDump probability, sybil wallet count, stake controlled (% of supply), and an estimated USD-saved figure (heuristic).
AI AnalysisOne-sentence senior-analyst commentary. Section is hidden when AI generation didn't run for that receipt.
ContractRaw address with Tonviewer deep-link.
Share buttonsPre-filled Twitter intent + "Get TonWise" CTA pointing at the bot.

Embedding in Your Product

Receipt URLs are stable and embeddable. If you operate a TON product (wallet, DEX, mini-app) that wants to surface threat context, you can:

  • Link https://tonguard.app/r/{id} from within your UI for any flagged contract.
  • Trust that Open Graph rendering works on Twitter, Telegram, Discord, Slack, iMessage out of the box.
  • Receipts are not gated by API key — they exist independently of the B2B endpoints.

To map a contract address to its receipt, query the Shield endpoint; if the contract has been flagged, the receipt will exist on its public URL within seconds of the Auto-Hunter catch.

Real-time Event Stream

Register an endpoint and receive signed payloads the moment Auto-Hunter detects a threat. No polling required.

POST /api/v1/webhook/register Register endpoint

Body Parameters

ParameterTypeDescription
url string required HTTPS endpoint to receive events
events string[] optional Event types to subscribe. Default: all
secret string optional HMAC secret. Auto-generated if omitted

Example Request

curl
curl -X POST https://tonguard.app/api/v1/webhook/register \
  -H "X-API-Key: tw_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-bot.com/hook","events":["dump_alert","spoof","sybil_cluster"]}'

Response

json
{
  "webhook_id":  1,
  "url":         "https://your-bot.com/hook",
  "events":      ["dump_alert", "spoof", "sybil_cluster"],
  "secret":      "a3f9b2c1d4e5...",
  "created_at":  "2026-05-02T10:00:00Z",
  "hint":        "Store the secret securely — used to verify HMAC signatures"
}
POST /api/v1/webhook/test Fire test payload
curl
curl -X POST https://tonguard.app/api/v1/webhook/test \
  -H "X-API-Key: tw_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"webhook_id": 1}'
GET /api/v1/webhook/list List registered webhooks
curl
curl https://tonguard.app/api/v1/webhook/list \
  -H "X-API-Key: tw_live_your_key"
DELETE /api/v1/webhook/{webhook_id} Disable webhook
curl
curl -X DELETE https://tonguard.app/api/v1/webhook/1 \
  -H "X-API-Key: tw_live_your_key"

Event Types

dump_alert
Micro test-transactions detected from Puppet Master to Sybils. Coordinated sell typically follows within hours.
sybil_cluster
5+ wallets funded from a single source. Supply artificially concentrated. Manipulation risk elevated.
spoof
Token name contains invisible Unicode characters impersonating USDT, TON or other known assets.
pump_warning
Unusual buy pressure pattern detected. Coordinated accumulation before distribution.

Payload Schema

Every webhook delivery includes the following fields plus an HMAC-SHA256 signature.

json
{
  "event":        "DUMP_ALERT",
  "contract":     "EQBHNioKtx8Fu3pglkxSzvl9zt4KY1ixUl0miMSVCyHvDW60",
  "symbol":       "TVL",
  "sybils":       22,
  "dump_prob":    92,
  "triggered_at": "2026-05-02T10:00:00Z",
  "source":       "tonguard.app",
  "signature":    "sha256=a3f9b2c1..."
}

Request Headers

HeaderValue
X-TonGuard-Signaturesha256=<hmac_hex>
X-TonGuard-EventDUMP_ALERT | SPOOF | SYBIL_CLUSTER
Content-Typeapplication/json

Verify Signature

Always verify the HMAC-SHA256 signature before processing a webhook payload.

python
import hashlib, hmac

def verify(secret: str, payload: bytes, sig_header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, sig_header)
javascript
const crypto = require('crypto');

function verify(secret, payload, sigHeader) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(sigHeader)
  );
}

Error Codes

StatusCodeDescription
401 Unauthorized Missing or invalid X-API-Key
403 Forbidden API key expired or subscription inactive
429 Rate Limited Daily scan limit reached. Check X-RateLimit-Remaining
503 Upstream Error TONAPI temporarily unavailable. Retry after 30s
💬 Questions or integration issues? Reach out at @TonWiseDev