API Documentation
REST API for real-time Bitcoin on-chain intelligence. All endpoints return JSON.
Overview
Base URL: https://dashboard.btcwhalealerts.com/v1
Auth: Bearer token or HMAC signature (see below)
Format: JSON (UTF-8)
Tier: Research (T3) — 149 CHF/month, 100,000 requests/month, 60 requests/minute
Authentication
Two auth methods are supported. Pick the one that fits your client.
Method 1: Bearer Token (simple)
Pass the full token in the Authorization header:
Authorization: Bearer swi_live_<keyid>_<secret>
Tokens have the format swi_live_<keyid>_<secret> — e.g. swi_live_ExampleKeyId_ExampleSecretNotARealKey (illustration only, not a live token). The public keyid identifies the key; the secret authenticates it. The token is stored hashed on our side — we never log the plaintext.
Method 2: HMAC Signature (enterprise)
For clients that require signed requests (no secret leakage even if TLS is MITM'd):
Authorization: Bearer swi_live_<keyid>
X-Timestamp: 1776368400
X-Signature: sha256=<hex(hmac_sha256(secret, "{ts}.{method}.{path}.{body}"))>
Timestamp must be within ±300 seconds of server time. Body is the raw request body (empty string for GET).
export SWI_TOKEN="swi_live_xxx_yyy"
curl "https://dashboard.btcwhalealerts.com/v1/stats" \
-H "Authorization: Bearer $SWI_TOKEN" | jq
Rate Limits
Every response includes these headers:
X-RateLimit-Limit-Monthly— your monthly quota (default 100k)X-RateLimit-Limit-Per-Min— per-minute ceiling (default 60)X-API-Tier—research
When exceeded, you get HTTP 429 Too Many Requests with a Retry-After header (seconds). The monthly counter resets on the 1st of each month UTC.
Errors
All errors follow this shape:
{
"error": {
"code": "invalid_key",
"message": "API key not found or revoked"
}
}
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_address, invalid_txid | Malformed input |
| 401 | missing_auth, invalid_key, invalid_secret, hmac_failed | Auth failure |
| 404 | not_found | Resource doesn't exist or is outside our dataset |
| 429 | rate_limit_exceeded | Quota exhausted — check Retry-After |
| 500 | internal_error | Server error (please report) |
Endpoints
Health check. Returns {"ok": true, "time": "..."}. No auth required.
Coverage + activity snapshot.
Response
{
"addresses_monitored": 831315,
"whale_trades_total": 3108897,
"whales_today": 898,
"volume_today_btc": 532528.2,
"btc_price_usd": 75256.0,
"fear_greed_index": 23,
"fear_greed_label": "Extreme Fear"
}
Recent whale transactions, reverse-chronological. Filterable by flow type and size.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit | int | 50 | Max rows (capped at 500) |
min_btc | float | 100 | Minimum total_btc threshold |
flow | string | — | to_exchange · from_exchange · wallet_to_wallet · exchange_to_exchange |
before | string | — | Opaque pagination cursor from the previous page's next_cursor field. Works for the full historical dataset. |
since_id | int | — | Legacy frontier-streaming cursor (only rows since 2026-04 with populated id). Use before for historical pagination. |
lang | string | en | Intent-text language (en, de, es) |
Response (1 row shown)
{
"data": [{
"id": 4912345,
"txid": "abc123...",
"timestamp": "2026-04-16T20:09:15+00:00",
"total_btc": 847.5,
"from_address": "bc1q...",
"to_address": "3Abc...",
"recipient_trust": 0.94,
"score": 9,
"flow_type": "to_exchange",
"flags": "mega_whale,exchange_flow",
"block_height": 945128,
"intent": {
"code": "distribution",
"text": "Likely distribution — whale moved to exchange",
"confidence": 0.9,
"emoji": "🔴"
}
}],
"count": 1
}
Intent codes: distribution · accumulation · exchange_shift · treasury_move · cold_storage · new_whale · otc_likely · neutral. See Intent classification.
Detailed metadata for a single transaction. Returns 404 if the transaction is not in our whale dataset (i.e. below the capture threshold).
Aggregated metrics for a Bitcoin address: balance, total in/out, first/last seen, trust index, spike score, entity label (if known). Returns 404 if address is not in our watchlist.
Confidence-weighted community sentiment across 7 sources (Telegram, Reddit, Bluesky, Farcaster, News, Google Trends, Fear & Greed).
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
hours | int | 24 | Lookback window in hours (max 720 = 30 days) |
Response
{
"window_hours": 24,
"overall": {
"score": 0.248, // range -1.0 (bearish) to +1.0 (bullish)
"label": "neutral",
"mentions": 368
},
"platforms": {
"telegram": {"score": 0.15, "mentions": 120},
"reddit": {"score": 0.32, "mentions": 62},
"bluesky": {"score": 0.23, "mentions": 90},
"farcaster":{"score": 0.35, "mentions": 64},
"news": {"score": 0.23, "mentions": 58},
"google_trends":{"score": 0.31, "mentions": 10},
"fear_greed": {"score": -0.54, "mentions": 1}
}
}
Intent Classification
Every whale transaction comes with a heuristic intent classification — a single-sentence interpretation of what the move likely signals. This is transparent and deterministic (no ML black-box): rules based on flow type, entity labels, amount, and recipient trust score.
| Code | Emoji | Meaning | Trigger |
|---|---|---|---|
distribution | 🔴 | Whale moved to exchange — potential sell pressure | flow to exchange |
accumulation | 🟢 | Withdrawal from exchange — potential hodl | flow from exchange |
exchange_shift | 🔄 | Exchange-to-exchange shift — OTC / custody reroute | both sides exchange |
cold_storage | ❄️ | Exchange → unknown address ≥500 BTC | large, no recipient entity |
treasury_move | 🏦 | Internal move between known entities | both sides known (non-exchange) |
new_whale | 🆕 | Recipient not previously tracked | trust=0, amount ≥200 BTC |
otc_likely | 💼 | Round amount, w2w, large | heuristic: 500/1000/2500 BTC etc. |
neutral | ⚪ | No strong signal | default |
Versioning
This is API v1. Breaking changes go into v2. We commit to maintaining v1 for at least 12 months after v2 ships.
Support
Issues, feature requests, or bulk/enterprise inquiries: dev@btcwhalealerts.com