Buildix is an institutional-grade orderflow analytics platform for DEX and CEX perpetual trading. Access real-time CVD, VPIN, OBI, whale tracking and signal data over a REST API from Python, JavaScript or cURL. All endpoints are documented below. There is no WebSocket: the platform is serverless and holds no connections, so consumers poll, and the feed endpoints report their producer cadence so you know how often that is worth doing.
Add Buildix to Claude, ChatGPT, Le Chat, Perplexity, Grok or any MCP client. Free mode: one URL, five read-only tools, no account and no key. API mode: the same API keys and daily quota as the REST API, seven plan-gated tools with raw values.
https://www.buildix.trade/api/mcp/publicBoth modes and the setup for each assistant: AI Integrations (API mode).
Funding annualization, October 2, 2026. fundingAnnualized (screener, pair, signals, CSV export) and funding_annualized_pct (alert webhooks) are now annualized on the venue's real settlement interval. Hyperliquid and dYdX settle hourly, so on Hyperliquid the values are about 8 times the previous ones for the same rate. funding, the raw hourly rate, does not change. In /api/v1/funding-arb every venue carries intervalHours, annualized uses it, and spread and spreadAnnualized compare hourly equivalent rates.
Counted per API key, reset at Europe/Rome midnight (not UTC). Exhausting it returns HTTP 429 with a Retry-After header holding the seconds until the reset. Whale moved from 50,000 to 2,000 requests per day in September 2026 and the 50,000 allowance moved to the API plan; a Whale subscription that started before 8 September 2026 keeps 50,000 per day for 60 days from that date. Read /api/v1/usage for the limit actually applied to your key.
The burst guard runs at the edge and does not depend on your plan. It is keyed by identity: your IP address, or your IP plus the public prefix of the key when you send one, so a shared office address is not punished for one noisy key. Going over returns HTTP 429 with the window in the body and an accurate Retry-After.
Every tradable Hyperliquid perpetual with mark price, 24h change, 24h volume, open interest in USD and funding (raw hourly rate + annualized as rate x 24 x 365). No API key required; a key only raises the daily quota.
curl "https://www.buildix.trade/api/v1/screener" # A key is optional here, and raises the daily quota: curl "https://www.buildix.trade/api/v1/screener" \ -H "Authorization: Bearer YOUR_API_KEY"
Generate an API key from your Dashboard → API Keys. Include it in every request as a Bearer token. Keys look like bx_ followed by 32 hex characters — there is no bx_live_ / bx_test_ split.
Authorization: Bearer bx_0123456789abcdef0123456789abcdef
Two other spellings are accepted, in this order of priority: the header x-api-key: bx_..., and, only where a client cannot set a custom header at all, the query parameter ?api_key=bx_.... A key in a URL can be captured by your own client logs and by any proxy in between, so keep the query form for connectors that leave you no choice and give those a dedicated key.
/api/v1/screener and /api/v1/pair/{symbol} answer without a key; a key on those only raises the daily quota. Every other endpoint requires one. An invalid or revoked key returns 401, a plan below the endpoint returns 403 naming the tier required, and an exhausted daily quota returns 429.
Buildix can POST events to your own server: Entry Signals, their outcome four hours later, and your alerts. Register an endpoint in Dashboard → Alerts (5 endpoints on Pro, 20 on Whale and API). Each endpoint gets a signing secret, shown once, that you can rotate.
entry_signal.created: a new Entry Signal matching an Entry Signal alert that uses the endpoint (same pairs, timeframe and minimum grade as the Telegram and email channel). Pro and above. On HIP-3 markets (symbols such as xyz:NVDA) a signal whose bar falls outside the market's trading session is sent with its grade lowered one step and two extra fields in data: session ("closed") and grade_before_session. Crypto signals and open-session signals never carry them.signal.outcome: four hours after each delivered signal, the move in the signal's direction, the best and worst excursion and which level was touched first. Computed from the 5m bars Buildix already holds, with the same price rule as the public channel follow up.alert.triggered: an alert (price, screener, sweep, delta flip, drawing) whose webhook URL is a registered endpoint. data carries the same fields as the previous flat payload, plus alert_kind.test: sent by the Send test event button.Every event has the same envelope. id is stable: a retry of the same event carries the same id, so store it and ignore duplicates. New fields may be added to data; a breaking change would ship as version "2".
{
"id": "evt_9f2c41d0b6a84e5f8c1d2e3f4a5b6c7d",
"type": "entry_signal.created",
"version": "1",
"created_at": "2026-09-26T10:15:04.211Z",
"data": {
"signal_id": "BTC-15m-1758880800000-long",
"symbol": "BTC",
"timeframe": "15m",
"side": "long",
"grade": "A",
"score": 0.81,
"bar_time": "2026-09-26T10:00:00.000Z",
"regime": "trend_up",
"confirmed": true,
"flow_source": "trades",
"logics": { "liquidity_grab": true, "flow_rejection": true, "absorption": false,
"cvd_divergence": true, "structure_shift": false, "level_confluence": true },
"plan": { "entry": 64210.5, "stop": 63880.0, "t1": 64706.0, "t2": 65201.5, "r_t1": 1.5, "r_t2": 3 },
"price_at_signal": 64215.0,
"chart_url": "https://www.buildix.trade/pair/BTC"
}
}{
"id": "evt_0b7e...",
"type": "signal.outcome",
"version": "1",
"created_at": "2026-09-26T14:15:30.002Z",
"data": {
"entry_event_id": "evt_9f2c41d0b6a84e5f8c1d2e3f4a5b6c7d",
"signal_id": "BTC-15m-1758880800000-long",
"symbol": "BTC", "timeframe": "15m", "side": "long", "grade": "A",
"horizon": "4h",
"signaled_at": "2026-09-26T10:15:04.211Z",
"evaluated_at": "2026-09-26T14:15:30.002Z",
"price_at_signal": 64215.0,
"price_after": 64890.0,
"move_pct": 1.0512,
"max_favorable_pct": 1.4201,
"max_adverse_pct": -0.3105,
"first_level_hit": "t1",
"t2_hit": false
}
}first_level_hit is stop, t1, none, or both_same_bar when one 5m bar spans both levels and the order inside the bar is unknown.
Content-Type: application/json X-Buildix-Event: entry_signal.created X-Buildix-Event-Id: evt_9f2c41d0b6a84e5f8c1d2e3f4a5b6c7d X-Buildix-Delivery: <uuid of this delivery> X-Buildix-Attempt: 1 X-Buildix-Timestamp: 1758881704 X-Buildix-Signature: v1=<hex HMAC-SHA256(secret, "<timestamp>.<raw body>")>
Compute the HMAC over the timestamp, a dot and the raw request body exactly as received, and compare in constant time. Reject a timestamp more than 300 seconds away from your clock (replay protection) and an event id you already handled. For 24 hours after a rotation the header carries two entries, v1=<new>,v1=<old>: accept the request when any entry matches.
// Node 18+ (Express). Verify on the RAW body, before JSON parsing.
import crypto from 'node:crypto';
import express from 'express';
const SECRET = process.env.BUILDIX_WEBHOOK_SECRET; // whsec_...
const TOLERANCE_S = 300;
const seen = new Set(); // use your database in production
function verify(rawBody, timestamp, signatureHeader) {
if (!timestamp || !signatureHeader) return false;
const ts = Number(timestamp);
if (!Number.isInteger(ts) || Math.abs(Date.now() / 1000 - ts) > TOLERANCE_S) return false;
const expected = crypto.createHmac('sha256', SECRET).update(`${ts}.${rawBody}`).digest();
return signatureHeader.split(',').some((part) => {
const [scheme, hex] = part.trim().split('=');
if (scheme !== 'v1' || !/^[0-9a-f]{64}$/.test(hex || '')) return false;
return crypto.timingSafeEqual(Buffer.from(hex, 'hex'), expected);
});
}
const app = express();
app.post('/buildix', express.raw({ type: 'application/json' }), (req, res) => {
const raw = req.body.toString('utf8');
if (!verify(raw, req.get('X-Buildix-Timestamp'), req.get('X-Buildix-Signature'))) {
return res.status(401).end();
}
const event = JSON.parse(raw);
if (seen.has(event.id)) return res.status(200).end(); // retry of an event already handled
seen.add(event.id);
res.status(200).end(); // answer fast, work after
// handle event.type / event.data here
});
app.listen(3000);# Python 3.10+ (Flask). Verify on the RAW body, before JSON parsing.
import hashlib, hmac, json, os, time
from flask import Flask, request, abort
SECRET = os.environ["BUILDIX_WEBHOOK_SECRET"].encode() # whsec_...
TOLERANCE_S = 300
seen = set() # use your database in production
def verify(raw: bytes, timestamp: str | None, signature_header: str | None) -> bool:
if not timestamp or not signature_header or not timestamp.isdigit():
return False
if abs(time.time() - int(timestamp)) > TOLERANCE_S:
return False
expected = hmac.new(SECRET, f"{timestamp}.".encode() + raw, hashlib.sha256).hexdigest()
for part in signature_header.split(","):
scheme, _, value = part.strip().partition("=")
if scheme == "v1" and hmac.compare_digest(value, expected):
return True
return False
app = Flask(__name__)
@app.post("/buildix")
def buildix():
raw = request.get_data()
if not verify(raw, request.headers.get("X-Buildix-Timestamp"), request.headers.get("X-Buildix-Signature")):
abort(401)
event = json.loads(raw)
if event["id"] in seen:
return "", 200 # retry of an event already handled
seen.add(event["id"])
# handle event["type"] / event["data"] here
return "", 200Need API access?
The screener and pair endpoints are open, so you can build against them before you pick a plan. A key raises the daily quota and unlocks the gated endpoints; the burst limit per minute is the same on every plan.