TonWise API
Real-time on-chain security layer for TON. Detect Puppet Masters, Sybil clusters and Unicode spoofs before your users lose money.
Authentication
Pass your API key in the X-API-Key header on every request.
curl https://tonguard.app/api/v1/shield \ -H "X-API-Key: tw_live_your_key_here" \ -G -d "contract=EQBHNioK..."
Rate Limits
Shield API responses are Redis-cached. Cache miss triggers live blockchain analysis (~2-5s). Cache hit returns in <50ms.
| Plan | Limit | Cache TTL |
|---|---|---|
| Free (B2C) | 10 scans/day per IP | 24h |
| Pro | Unlimited | 24h |
| Enterprise | Custom SLA | Configurable |
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.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contract | string | required | TON contract address (EQ... or 0:...) |
Example Request
curl "https://tonguard.app/api/v1/shield?contract=EQBHNioKtx8Fu3pglkxSzvl9zt4KY1ixUl0miMSVCyHvDW60" \ -H "X-API-Key: tw_live_your_key"
Response
{
"contract": "EQBHNioKtx8Fu3pglkxSzvl9zt4KY1ixUl0miMSVCyHvDW60",
"is_safe": false,
"dump_probability": 45,
"reason": "SYBIL_CONCENTRATION_DETECTED",
"sybil_clusters": 1
}
Reason Codes
| Reason | Description |
|---|---|
| CLEAN | No threats detected |
| SYBIL_CONCENTRATION_DETECTED | Puppet Master + Sybil cluster found |
| DUMP_IMMINENT | Micro test-transactions detected, sell incoming |
| CROSS_CHAIN_EXIT_* | Liquidity draining via bridge |
| INVALID_CONTRACT_OR_NO_HOLDERS | Contract not found or empty |
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.
current_tier field for graceful upgrade prompts.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| address | string | required | TON address. Accepts user-friendly (EQ.../UQ...) or raw (0:hex) format — server canonicalizes on input. |
Example Request
curl "https://tonguard.app/api/v1/threat-intel/EQDa4VOnTYlLvDJ0gZjNYm5PXfSmmtL6Vs6A_CZEtXCNICq_" \ -H "X-API-Key: tw_live_your_scale_key"
Python SDK
from tonwise import TonWiseClient, TierError with TonWiseClient(api_key="tw_live_your_scale_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 Scale 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)
{
"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
| Field | Type | Description |
|---|---|---|
| address | string | Canonical raw form (0:hex), regardless of input format. Echo for client-side cache keying. |
| threat_score | int 0-100 | Nonlinear function of bad-edge density in the cluster. 0 = clean, 100 = saturated with flagged neighbors. Use ≥70 as a hard-block threshold. |
| associated_addresses | int | Total nodes visited in BFS (excluding the queried address). Capped at 5000 for predictable latency. |
| linked_scams[] | array | Top 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[] | array | Tags on the queried address itself, present only if it's flagged. Common values: "SCAM", "PUPPET_MASTER", "PHISHING". |
| puppet_master_cluster_id | string? | Cluster ID if address belongs to a known Sybil cluster. Currently always null; populated as Lazarus clustering API expands. |
| cross_chain_exits[] | array | Bridge exit history. Currently always empty; populated when KNOWN_INFRASTRUCTURE mapping ships in a future release. |
| first_seen / last_activity | string? | Per-address timestamps. Currently always null; planned for the next graph-layer iteration. |
| graph_depth | int | BFS depth used (currently fixed at 3). |
| computed_at | string | ISO-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):
{
"error": "Threat Intel API requires Scale 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.
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
Receiptrow 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
| Element | Description |
|---|---|
| Severity badge | CRITICAL / HIGH / MEDIUM / LOW with color-coded border. Severity is floored at MEDIUM for any receipt that came from a publish-gated alert. |
| Threat ID | Stable identifier in TW-YYYY-XXXX format. Same contract gets the same ID within a calendar year. |
| Stats grid | Dump probability, sybil wallet count, stake controlled (% of supply), and an estimated USD-saved figure (heuristic). |
| AI Analysis | One-sentence senior-analyst commentary. Section is hidden when AI generation didn't run for that receipt. |
| Contract | Raw address with Tonviewer deep-link. |
| Share buttons | Pre-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.
Body Parameters
| Parameter | Type | Description | |
|---|---|---|---|
| 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 -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
{
"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"
}
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}'
curl https://tonguard.app/api/v1/webhook/list \ -H "X-API-Key: tw_live_your_key"
curl -X DELETE https://tonguard.app/api/v1/webhook/1 \ -H "X-API-Key: tw_live_your_key"
Event Types
Payload Schema
Every webhook delivery includes the following fields plus an HMAC-SHA256 signature.
{
"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
| Header | Value |
|---|---|
| X-TonGuard-Signature | sha256=<hmac_hex> |
| X-TonGuard-Event | DUMP_ALERT | SPOOF | SYBIL_CLUSTER |
| Content-Type | application/json |
Verify Signature
Always verify the HMAC-SHA256 signature before processing a webhook payload.
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)
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
| Status | Code | Description |
|---|---|---|
| 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 |