Sign in to get a session token (valid 24 h). Send it as ttc-auth-token with ttc-public-key. You can sign in from the dashboard. Without an account, pay per request instead (see Pricing & errors).
Base URL: https://www.tetrac.xyz/api/v1. Sign-in endpoints live under https://www.tetrac.xyz/api/auth.
The endpoint catalogue below is rendered from openapi.json and x402-services.json, the machine-readable contract. The free index GET /api/v1/markets lists every market endpoint with its price, with no payment or session needed.
Use @tetrac/login-sdk (authHeaders()) instead of calling these endpoints directly. It derives the keys in the browser, builds the signed messages below and keeps the session for you; hand-rolled key derivation is easy to get wrong.
authToken and publicKey. Send them on every authenticated request as the ttc-auth-token and ttc-public-key headers./api/v1 endpoint, a missing or expired session is answered with the 402 payment challenge, not 401. Sign in again to get a new token. Session-only endpoints (such as the MCP server) answer 401./api/auth errors have the body { "error": "<message>" }.ttc-auth-token: <authToken>
ttc-public-key: <publicKey>/api/auth/challengeIssue a one-time challenge for a wallet or email sign-in, registration or connect-wallet call.
publicKey (string)The account's Solana address (base58). Send this or email.
email (string)The account email, for email sign-in. Send this or publicKey.
appId (string)Optional. Must be "tetrac" when sent; that is also the default.
{
"challenge": "<64 hex characters>",
"pbkdf2Iterations": 600000
}400 Neither publicKey nor email, or a malformed value.429 Rate limit exceeded.A challenge is valid for 5 minutes and can be used once. pbkdf2Iterations is the count an email account derives its key with; Ledger accounts also get offchainEnvelope. An email with no account still gets a challenge, but no signature can redeem it.
/api/auth/login-walletSign in with a registered Solana wallet.
publicKey (string)requiredThe wallet's Solana address (base58).
signature (string)requiredHex-encoded ed25519 signature of the message below, made by that wallet (a 0x prefix is accepted).
challenge (string)requiredThe challenge issued for this publicKey.
appId (string)Optional. Must be "tetrac" when sent; that is also the default.
www.tetrac.xyz wants you to sign in with your Solana account:
<address>
Sign in to prove you own this wallet. This request does not send a transaction or cost any fees.
URI: https://www.tetrac.xyz
Version: 1
Nonce: <challenge>{
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authToken": "<64 hex characters>",
"user": {
"appId": "tetrac",
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authMethod": "wallet",
"wallets": [
{
"chain": "evm",
"role": "funds",
"publicKey": "0x1234…",
"encryptedSecret": "<ciphertext>"
}
],
"createdAt": 1760000000000
}
}400 A field is missing or malformed.401 Invalid credentials: a bad signature, or an expired or already-used challenge.422 The wallet is not registered. Use connect-wallet or register.429 Rate limit exceeded.A Ledger off-chain-message signature of the same text is accepted too.
/api/auth/connect-walletSign in with a Solana wallet, creating the account on first use (login-or-register in one call).
publicKey (string)requiredThe wallet's Solana address (base58).
signature (string)requiredHex-encoded ed25519 signature of the message below, made by that wallet.
challenge (string)requiredThe challenge issued for this publicKey.
wallets (array)Array of { chain, role, publicKey, encryptedSecret }, at most one per slot (solana/funds, solana/signing, evm/funds, evm/signing). encryptedSecret is ciphertext made in the browser under the account's app key (at most 8192 characters); the server stores it and cannot decrypt it. Stored only when the account is new or has no wallets yet.
offchainEnvelope (string)Ledger accounts only: "legacy" or "v0", the off-chain message layout the device signed.
appId (string)Optional. Must be "tetrac" when sent; that is also the default.
www.tetrac.xyz wants you to sign in with your Solana account:
<address>
Sign in to prove you own this wallet. This request does not send a transaction or cost any fees.
URI: https://www.tetrac.xyz
Version: 1
Nonce: <challenge>{
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authToken": "<64 hex characters>",
"user": {
"appId": "tetrac",
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authMethod": "wallet",
"wallets": [
{
"chain": "evm",
"role": "funds",
"publicKey": "0x1234…",
"encryptedSecret": "<ciphertext>"
}
],
"createdAt": 1760000000000
}
}400 A field is missing or malformed.401 Invalid credentials, including an email or passkey account that already uses this address.429 Rate limit exceeded, including the deployment-wide limit on new accounts.Returns 201 when it created the account and 200 when it signed into an existing one.
/api/auth/registerCreate an email, passkey or wallet account from a wallet bundle generated in the browser.
publicKey (string)requiredSolana address (base58) of the account's funds wallet. The challenge must have been issued for it.
signature (string)requiredHex-encoded ed25519 signature of the message below, made by that wallet's key.
challenge (string)requiredThe challenge issued for this publicKey.
authMethod (string)"email" (the default), "wallet" or "biometric".
authPublicKey (string)The account's ed25519 auth public key (64 hex characters), which email sign-in signatures are checked against. Required unless authMethod is "wallet".
email (string)The account email.
wallets (array)Array of { chain, role, publicKey, encryptedSecret }, at most one per slot (solana/funds, solana/signing, evm/funds, evm/signing). encryptedSecret is ciphertext made in the browser under the account's app key (at most 8192 characters); the server stores it and cannot decrypt it.
pbkdf2Iterations (integer)Email accounts: the PBKDF2 iteration count (100000 to 1000000) the browser derived the app key with. It is pinned for every later sign-in.
offchainEnvelope (string)Ledger accounts only: "legacy" or "v0".
appId (string)Optional. Must be "tetrac" when sent; that is also the default.
www.tetrac.xyz wants you to sign in with your Solana account:
<address>
Sign in to prove you own this wallet. This request does not send a transaction or cost any fees.
URI: https://www.tetrac.xyz
Version: 1
Nonce: <challenge>{
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authToken": "<64 hex characters>",
"user": {
"appId": "tetrac",
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authMethod": "wallet",
"wallets": [
{
"chain": "evm",
"role": "funds",
"publicKey": "0x1234…",
"encryptedSecret": "<ciphertext>"
}
],
"createdAt": 1760000000000
}
}400 A field is missing or malformed.401 Signature verification failed, or the challenge is invalid or expired.409 An account already exists for this address or email.429 Rate limit exceeded, including the deployment-wide limit on new accounts./api/auth/loginSign in to an email account.
email (string)requiredThe account email.
signature (string)requiredHex-encoded ed25519 signature of the message below, made by the account's auth key (the key behind authPublicKey).
challenge (string)requiredThe challenge issued for this email.
appId (string)Optional. Must be "tetrac" when sent; that is also the default.
Sign in to your TTC account: <challenge>{
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authToken": "<64 hex characters>",
"user": {
"appId": "tetrac",
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authMethod": "email",
"wallets": [
{
"chain": "evm",
"role": "funds",
"publicKey": "0x1234…",
"encryptedSecret": "<ciphertext>"
}
],
"createdAt": 1760000000000
}
}400 A field is missing or malformed.401 Invalid credentials.429 Rate limit exceeded.The SDK derives the auth key pair in the browser from the email and the passkey phrase. Neither the phrase nor any private key is sent to the server.
/api/auth/logoutRevoke the current session.
ttc-auth-token (string)requiredThe authToken from a sign-in response (64 hex characters, valid 24 h).
ttc-public-key (string)requiredThe publicKey from the same sign-in response.
{
"ok": true
}429 Rate limit exceeded.Always answers 200 { ok: true }, whether or not the token was valid; a valid session is revoked.
/api/auth/user-dataRead the signed-in account's record.
ttc-auth-token (string)requiredThe authToken from a sign-in response (64 hex characters, valid 24 h).
ttc-public-key (string)requiredThe publicKey from the same sign-in response.
{
"user": {
"appId": "tetrac",
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authMethod": "wallet",
"wallets": [
{
"chain": "evm",
"role": "funds",
"publicKey": "0x1234…",
"encryptedSecret": "<ciphertext>"
}
],
"createdAt": 1760000000000,
"gateway_grant": false,
"gateway_grant_symbol": null
}
}401 Missing, invalid or expired session.429 Rate limit exceeded.The record never contains the session token or a decryptable key: wallets carry only public keys and ciphertext.
/api/auth/user-dataSave one account preference.
ttc-auth-token (string)requiredThe authToken from a sign-in response (64 hex characters, valid 24 h).
ttc-public-key (string)requiredThe publicKey from the same sign-in response.
preferenceKey (string)required"migration" or "user_participation_preferences".
preferences (object)requiredThe value to store, at most 4 KB as JSON. user_participation_preferences must be { leaderboard: boolean, dao: boolean, lastUpdated: string }.
{
"success": true,
"message": "Preferences updated successfully"
}400 Unknown preferenceKey, a malformed value, or over 4 KB.401 Invalid or expired session.429 Rate limit exceeded./api/auth/import-walletAdd or replace wallet slots on the signed-in account.
ttc-auth-token (string)requiredThe authToken from a sign-in response (64 hex characters, valid 24 h).
ttc-public-key (string)requiredThe publicKey from the same sign-in response.
wallets (array)requiredArray of { chain, role, publicKey, encryptedSecret }, at most one per slot (solana/funds, solana/signing, evm/funds, evm/signing). encryptedSecret is ciphertext made in the browser under the account's app key (at most 8192 characters); the server stores it and cannot decrypt it. Each entry replaces the slot it names.
{
"user": {
"appId": "tetrac",
"publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
"authMethod": "wallet",
"wallets": [
{
"chain": "evm",
"role": "funds",
"publicKey": "0x1234…",
"encryptedSecret": "<ciphertext>"
}
],
"createdAt": 1760000000000
}
}400 wallets is missing or malformed.401 Missing, invalid or expired session.429 Rate limit exceeded./api/auth/search-walletCheck whether an account exists for a Solana address.
publicKey (string)requiredThe Solana address (base58) to look up.
appId (string)Optional. Must be "tetrac" when sent; that is also the default.
{
"exists": true
}400 publicKey is missing or malformed.429 Rate limit exceeded.A signed-in session calls every endpoint below at no charge, within the rate limits. Without a session, each call is paid in USDC on Solana. These are the endpoints Tetrac sells per request; other /api/v1 routes are not part of the paid catalogue.
| Endpoint | Name | Price |
|---|---|---|
| GET /api/v1/markets | Tetrac Markets Index | Free |
| GET /api/v1/markets/ttc-scanner | Tetrac Scanner | $0.05 USDC |
| GET /api/v1/markets/ttc-scanner-cache | Tetrac Scanner (All Markets) | $0.50 USDC |
| GET /api/v1/markets/hybrid-tickers | Tetrac Hybrid Tickers | $0.05 USDC |
| GET /api/v1/markets/funding-rates | Tetrac Funding Rates | $0.05 USDC |
| GET /api/v1/markets/open-interest | Tetrac Open Interest | $0.05 USDC |
| GET /api/v1/exchanges | Tetrac Exchanges (Read) | $0.05 USDC |
| POST /api/v1/exchanges | Tetrac Exchanges (Trade) | $0.05 USDC |
| GET /api/v1/markets/listings | Tetrac New Listings | $0.05 USDC |
| GET /api/v1/markets/insights | Tetrac Market Insights | $0.05 USDC |
| GET /api/v1/markets/news | Tetrac Market News | $0.05 USDC |
| GET /api/v1/markets/calendar | Tetrac Economic Calendar | $0.05 USDC |
| GET /api/v1/markets/swap-volume | Tetrac Perp DEX Volume History | $0.05 USDC |
| GET /api/v1/markets/volume-snapshot | Tetrac Volume Snapshot | $0.05 USDC |
| GET /api/v1/markets/quakes | Tetrac Market Quakes | $0.05 USDC |
| GET /api/v1/exchanges/latency | Exchange Latency | $0.05 USDC |
| GET /api/v1/markets/symbol-venues | Tetrac Symbol Venues | $0.05 USDC |
| GET /api/v1/solana-perps/long-short | Tetrac Solana Perps Long/Short | $0.05 USDC |
| GET /api/v1/solana-perps/pacifica-watchlist | Tetrac Pacifica Watchlist | $0.05 USDC |
x402Version: 2, accepts, resource); the same challenge is base64-encoded in the payment-required header. Each accepts entry names the USDC mint, the amount in micro-USDC and the payTo address.payTo on Solana mainnet from your own wallet. You sign the transfer and pay its network fee; Tetrac never signs or sponsors it.PAYMENT-SIGNATURE: base64({x402Version: 2, accepted, payload}), where payload is { signature, payer? } for a transfer that has landed, or { transaction } for a fully signed transaction the server relays (you stay the fee payer). This is what stock x402 clients send.x-x402-payment: x402:base64({signature, payer, amount}).X-Payment-Redeemed: false; a rate-limited call gets 429 with paymentRedeemed: false in its body. Either way the receipt is unspent and can be presented again.MPP alternative: the gateway POST /api/v1/mpp with { method, path, parameters } answers its own 402 (terms in WWW-Authenticate: Payment), charges USDC on Solana through the Machine Payments Protocol and forwards the paid call to the same endpoints at the same prices. Guide: MPP payments skill. The x402 walkthrough with examples is on the main docs page.
400 Bad or missing input. Returned before any payment is taken.401 A session-only endpoint without a valid session (for example POST /api/v1/markets/ttc-scanner-cache or the MCP server).402 Payment required: a fresh challenge, or a receipt that failed verification (no new terms).429 Rate limit exceeded, with Retry-After, X-RateLimit-Tier and X-RateLimit-Remaining.500 Unexpected server error.Every /api/v1 error body has success: false and an error field: a message string, or { error, details?, status? } from routes that use the shared error helper. A venue's own rejection of an exchange call comes back as 400 with the venue's message.
Limits run on a 60-second window per caller: the account for a session, the payer wallet for an x402 receipt, otherwise the client IP. x402 callers are limited at the free tier.
| Endpoints | Free | Pro (3×) | Elite (10×) |
|---|---|---|---|
/api/v1/exchanges, /api/v1/exchanges/latency | 20/min | 60/min | 200/min |
| Every other paid endpoint | 30/min | 90/min | 300/min |
/api/v1/exchanges$0.05 USDC per callExchange discovery read. Returns the methods catalog, the pricing summary and the live supportedExchanges roster, so an agent learns what it can trade and what each action costs.
Every call that targets a venue — account reads and trading alike — goes to POST /api/v1/exchanges, which carries exchange credentials in the request body. This GET never reads credentials — secrets in a query string leak into access logs, proxy logs and referrer headers — and takes no parameters: a non-empty method query parameter is rejected with 400 (the legacy list-methods=true is tolerated and returns the catalog).
An unpaid call receives the same methods, pricing and supportedExchanges fields inside its 402 challenge (a 402 for a payment that failed verification carries no catalog), so the catalog can be read before paying.
Returns {success, status, code, pricing, methods, supportedExchanges}. ($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)status (string)code (integer)pricing (object)methods (object) — Keyed by method name; every entry is run with POST /api/v1/exchangessupportedExchanges (string[]) — Venue ids accepted as exchangeName by POST /api/v1/exchanges200 Methods catalog, pricing summary and venue roster400 A non-empty method query parameter was sent — this GET takes none; run methods with POST /api/v1/exchanges. Returned before any payment is taken.402 Payment required (x402) — the body also carries methods, pricing and supportedExchanges429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/exchanges$0.05 USDC per callExchange dispatcher — runs one method against one venue. Every call that targets a venue goes through this POST, account reads included, so exchange credentials travel only in the request body. Body fields: exchangeName (a venue id from supportedExchanges in GET /api/v1/exchanges, case-insensitive), method, params (method-specific) and credentials (apiKey/apiSecret/passphrase/walletAddress).
IMPORTANT: trading methods execute REAL trades with REAL money. Always confirm parameters with the user before calling.
Methods and the credentials each needs (live descriptions: the methods catalog from GET /api/v1/exchanges):
credentials: getTickers, getBestBidAsk, getKlines, getContractSpecsapiKey + apiSecret: getBalance, getPositions, getOrders, getUserTradeHistory, getInfoLeverage, getDepositAddressapiKey only: getAccountsapiKey + apiSecret: placeMarketOrder, placeLimitOrder, placeStopOrder, cancelOrder, cancelAllOrders, closeAllPositions, setLeverage, setHedgeMode, createWithdrawalNot every venue implements every method; an unimplemented one returns 400. getPositions also records the returned positions for DAO analytics when the account has opted in to DAO participation.
params shape (varies by method):
placeMarketOrder — {symbol, side, quantity, reduceOnly?}placeLimitOrder — {symbol, side, quantity, price, timeInForce?, reduceOnly?}placeStopOrder — {symbol, side, quantity, stopPrice, ...}cancelOrder — {symbol, orderID, origClientOrderId?}cancelAllOrders, getOrders — {symbol?}, or the bare symbol stringgetBestBidAsk — {symbol}, or the bare symbol stringcloseAllPositions — {}setLeverage — {symbol, leverage}setHedgeMode — {symbol, isHedged}createWithdrawal — {currency, amount, address, chainName, addressTag?}: chainName is the venue's own network name (venues name networks differently) and addressTag is the memo/tag some networks require. Withdrawals are irreversible — confirm the asset, amount, destination address, network and tag with the user before every call. Not every venue supports withdrawals; an unsupported venue returns 400. The key must have withdrawal permission (most venues also require an IP whitelist and a pre-approved destination address), and the funds must already be in the venue's withdrawable wallet (usually spot/funding).Returns {success, data: <method-shaped result>, code, msg, exchange}; success is always true on a 200, so read code/msg for the venue's own status. ($0.05 USDC on Solana mainnet)
exchangeName (string)requiredVenue id from supportedExchanges, case-insensitive (normalised to lower case). Venue roster changes over time and is not enumerated here; the current list is returned by GET /api/v1/exchanges (including in its 402 discovery response, which requires no payment) and is shown on https://www.tetrac.xyz.
method (string; one of setHedgeMode, setLeverage, getInfoLeverage, getPositions, getBalance, placeLimitOrder, placeMarketOrder, placeStopOrder, closeAllPositions, createWithdrawal, getDepositAddress, getOrders, cancelAllOrders, cancelOrder, getUserTradeHistory, getAccounts, getTickers, getBestBidAsk, getKlines, getContractSpecs)requiredOne of the methods in the methods catalog from GET /api/v1/exchanges
params (object | string)Method-specific parameters. getOrders, getBestBidAsk and cancelAllOrders also accept the bare symbol string.
credentials (object)Exchange API credentials. Omit for the public market-data methods; getAccounts needs apiKey only; every other method needs apiKey and apiSecret.
Fields: apiKey, apiSecret, passphrase, walletAddress
success (boolean)data (any) — Method-shaped resultcode (integer)msg (string)exchange (string)200 Method result400 Bad input: the body is not a JSON object, exchangeName is missing or not a supported venue, method is not a supported exchange method, credentials are missing for a credentialed method, the method is not implemented on this venue, or the venue rejected the call. Every case except the venue rejecting the call is returned before any payment is taken.402 Payment required (x402) — the body also carries methods, pricing and supportedExchanges429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server errorPOST https://www.tetrac.xyz/api/v1/exchanges
{
"exchangeName": "binance",
"method": "getTickers",
"params": {}
}/api/v1/exchanges/latency$0.05 USDC per callProbes every configured venue from Tetrac's servers and returns two independent measurements per exchange: a TLS-handshake time (tlsLatency/tlsStatus) and a full data-endpoint roundtrip (dataLatency/dataStatus), plus the resolved hostname, ip, hosting org and static tickerCount. Takes no parameters — every configured venue is probed on each call. Rows are sorted data-online first, then by ascending data latency. Use to pick the lowest-latency venue for execution, or to detect a venue whose API is degraded while its edge is still up. ($0.05 USDC on Solana mainnet)
No query parameters.
summary (object) — Aggregate counts and mean latency, split per probe typeexchanges (ExchangeLatency[])timestamp (integer) — Epoch ms when the probe run completed200 Per-exchange latency probe results plus aggregate summary402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Probe run failedThe method values the dispatcher accepts, with the credentials each needs. Not every venue implements every method; an unimplemented one returns 400.
| Method | Description | Credentials |
|---|---|---|
setHedgeMode | Set hedge mode for the exchange account | apiKey + apiSecret |
setLeverage | Set leverage for a specific trading pair | apiKey + apiSecret |
getInfoLeverage | Get the leverage tier brackets for a specific trading pair (notional ranges and their max leverage caps) | apiKey + apiSecret |
getPositions | Retrieve current open positions | apiKey + apiSecret |
getBalance | Get account balance information | apiKey + apiSecret |
placeLimitOrder | Execute a limit order (filled when price reaches specified level) | apiKey + apiSecret |
placeMarketOrder | Execute a market order (filled immediately at current price) | apiKey + apiSecret |
placeStopOrder | Place a stop order that triggers at a specified price | apiKey + apiSecret |
closeAllPositions | Close all open positions for the account | apiKey + apiSecret |
createWithdrawal | Initiate a withdrawal from the exchange | apiKey + apiSecret |
getDepositAddress | Get deposit address for a specific asset | apiKey + apiSecret |
getOrders | Retrieve open or historical orders | apiKey + apiSecret |
cancelAllOrders | Cancel all open orders for the account | apiKey + apiSecret |
cancelOrder | Cancel a specific order by ID | apiKey + apiSecret |
getUserTradeHistory | Retrieve user's historical trade records | apiKey + apiSecret |
getAccounts | List the user's Propr challenge-attempt accounts (onboarding account picker; Propr only) | apiKey |
getTickers | Get current ticker information for trading pairs | none (public market data) |
getBestBidAsk | Get best bid and ask prices for a trading pair | none (public market data) |
getKlines | Get historical candlestick/kline data for a trading pair | none (public market data) |
getContractSpecs | Get per-market contract size, size increment and order minimums (canonical symbols) | none (public market data) |
curl -X POST https://www.tetrac.xyz/api/v1/exchanges \
-H "ttc-auth-token: <authToken>" \
-H "ttc-public-key: <publicKey>" \
-H "Content-Type: application/json" \
-d '{
"exchangeName": "binance",
"method": "placeMarketOrder",
"params": { "symbol": "BTCUSDT", "side": "buy", "quantity": 0.01 },
"credentials": {
"apiKey": "<binance_api_key>",
"apiSecret": "<binance_api_secret>"
}
}'Trading methods execute real trades with real money. The credentials travel in the body of each request and are not stored by the server.
curl -X POST https://www.tetrac.xyz/api/v1/exchanges \
-H "ttc-auth-token: <authToken>" \
-H "ttc-public-key: <publicKey>" \
-H "Content-Type: application/json" \
-d '{
"exchangeName": "orderly",
"method": "getPositions",
"params": {},
"credentials": {
"apiKey": "<orderly_trading_wallet_public_key>",
"apiSecret": "<orderly_trading_wallet_private_key>",
"passphrase": "ttc"
}
}'For Orderly, apiKey is the ed25519 trading-wallet public key (raw, no prefix), apiSecretis that wallet's private key and passphrase is the broker ID. Your account address is taken from ttc-public-key unless you send credentials.walletAddress.
This call sends your Orderly private key to Tetrac's server, which signs the request with it and does not store it. The in-app default for Orderly is Lite routing, which signs in your browser and does not send the key.
/api/v1/marketsFreeFree discovery index for every /api/v1/markets/* endpoint — no payment and no session required. Returns {pricing, methods}: pricing is the standard per-request price of the listed endpoints {amount, currency, network, per}, and methods is keyed by sub-route slug (e.g. funding-rates) with {name, path, method, description, price: {amount, currency}} per entry, plus params on the entries that take query parameters, so an agent can see what each paid endpoint costs before paying for any of them. Rate-limited per client (per account when a session is presented); over the limit it returns 429 with Retry-After. (Free)
No query parameters.
success (boolean)status (string)code (integer)pricing (object)methods (object) — Keyed by sub-route slug, e.g. funding-rates200 Endpoint catalog and pricing summary429 Rate limit exceeded — retry after Retry-After seconds/api/v1/markets/ttc-scanner$0.05 USDC per callRuns a multi-timeframe Quadrant-lines technical scan for one symbol. Returns {params: {symbol, timeframe, bars, swingStrength}, data: {symbol, price, scans, scoring, signal, breakout}}: scans holds the per-timeframe scan results, scoring the long/short fan-line scores, signal the trade signal (direction LONG|SHORT|NEUTRAL, strength, confidence, entry, stopLoss, takeProfit1..3, riskRewardRatio, reasoning; the levels are null when no trade is signalled) and breakout a volatility-squeeze breakout read. Use as a one-call signal generator for one symbol and timeframe. ($0.05 USDC on Solana mainnet)
symbol (string)requiredMarket symbol
timeframe (string; one of 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M · default 1h)Binance USDⓈ-M futures kline interval (1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M; 1M is one month). Any other value returns 400 before payment.
bars (integer; default 1000 · min 50 · max 1000)Number of historical bars to analyze, from 50. Defaults to 1000; larger values are clamped to 1000. Any other value returns 400 before payment.
swingStrength (integer; default 10 · min 1 · max 100)Pivot sensitivity in bars, 1 to 100; higher values report only larger swings. Defaults to 10. Any other value returns 400 before payment.
success (boolean)timestamp (integer)params (object)data (object)200 Scanner result with signal400 Missing or invalid query parameter, returned before any payment is taken402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected error, or fewer than 50 bars of history for the symbol (an unknown or newly listed market)GET https://www.tetrac.xyz/api/v1/markets/ttc-scanner?symbol=BTCUSDT&timeframe=1h/api/v1/markets/ttc-scanner-cache$0.50 USDC per callThe latest cached technical-analysis signals for every scanned market. Without parameters it returns only the snapshot's freshness — generatedAt and staleAtMs (epoch ms; generatedAt is null before the first sweep) — so a client can check age before fetching. ?full=1 returns the snapshot itself: data: {generatedAt, universe, symbols[{symbol, quoteVolume, signal, breakout}], meta: {universeSize, scanned, skipped, durationMs, submitted?, dropped?}}. Both modes are priced the same, so pass full=1 to receive the signals.
The snapshot counts as stale 55 minutes after generatedAt (staleAtMs). Tetrac's app refreshes it at most once every 55 minutes, on no fixed schedule, so check staleAtMs before relying on the signals. ($0.50 USDC on Solana mainnet)
full (string; one of 0, 1)1 returns the full snapshot in data; 0 or omitted returns the freshness fields only. Any other value returns 400 before payment.
success (boolean)timestamp (integer)generatedAt (integer) — Without full=1: epoch ms of the last sweep, null if nonestaleAtMs (integer) — Epoch ms when the snapshot becomes eligible for a refresh, or null if none exists yetdata (object) — Only with full=1200 Snapshot freshness, or the full snapshot with ?full=1400 Invalid full value, returned before any payment is taken402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/hybrid-tickers$0.05 USDC per callReturns the cross-exchange perpetual futures ticker set from one server-side cache: data.futures.data is an array of Ticker objects (Binance-style 24h fields, numeric values as decimal strings), where source/sources name the venues that list each market and volumeByExchange splits its volume by venue. Use it to screen markets in one paid call instead of calling each venue. Every filter is optional; a missing, non-numeric or out-of-range value is ignored rather than rejected. health returns the cache's health record instead of tickers. ($0.05 USDC on Solana mainnet)
type (string)Market type. Only futures is served; any other value is ignored and futures are returned.
symbol (string)Exact symbol match (upper-cased before comparing).
exchange (string)Keep only markets listed on this venue (matched against source and sources, case-insensitive).
minimumVolume (number; min 0)Minimum 24h quote volume in USD (quoteVolume).
minimumPrice (number; min 0)Minimum lastPrice. Swapped with maximumPrice if it is the larger of the two.
maximumPrice (number; min 0)Maximum lastPrice.
up (number; min -100 · max 10000)Keep markets whose 24h priceChangePercent is at least this value.
down (number; min 0 · max 100)Keep markets down at least this many percent over 24h.
health (string)Any value: return data = {status, redis, lastError, lastSuccessfulFetch, timeSinceLastFetch} (the ticker cache's health) instead of tickers.
success (boolean)data (object)timestamp (integer)cached (boolean)cacheInfo (object)warning (string) — Optional advisory about the cache's state200 Perpetual tickers402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server errorGET https://www.tetrac.xyz/api/v1/markets/hybrid-tickers?exchange=binance&minimumVolume=10000000/api/v1/markets/funding-rates$0.05 USDC per callReturns an array of perpetual-futures funding entries (exchange, symbol, fundingRate, intervalHours, hourlyRate, dailyRoi, nextFundingTime) live across major perp venues. Use to spot funding-rate arbitrage between venues, monitor extreme rates that signal crowded positioning, or rank perps by funding cost. Optional filters: symbol, exchange and arb. A top-level error string lists venues that failed during the refresh, when any did. ($0.05 USDC on Solana mainnet)
Comparing venues: fundingRate is each venue's NATIVE per-interval rate, and that interval differs per MARKET — not merely per exchange. A single venue commonly runs 1h, 4h and 8h markets side by side, so raw fundingRate values are not comparable across rows. Use hourlyRate (rate normalized to a 1-hour basis) for any cross-venue comparison, and dailyRoi (hourlyRate x 24) for a rough 24h projection.
hourlyRate and dailyRoi are omitted when the market's settlement interval could not be established, rather than being estimated from a default. intervalSource is always present and is unknown in exactly that case.
symbol (string)Only this symbol. Also widens the query to venues that have no bulk funding endpoint, which are skipped when no symbol is given; rows are then sorted by exchange.
exchange (string)Comma-separated venue ids to keep (case-insensitive).
arb (integer; min 1)Return only the N highest and N lowest fundingRate rows, sorted by fundingRate descending.
success (boolean)data (FundingRate[])cached (boolean)timestamp (integer)error (string) — Present when some venues failed during the refresh200 Funding rate data402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/open-interest$0.05 USDC per callReturns the latest open-interest snapshot from one venue — chosen by source, default bybit — for the Binance perpetual markets that venue also lists, sorted by 24h volume: {data: [{symbol, openInterest, openInterestUsd, price, volumeUsd, timestamp}], timestamp, source}. Numeric values are decimal strings. The snapshot is cached for 5 minutes. Use to detect open-interest build-up that often precedes price moves. ($0.05 USDC on Solana mainnet)
source (string)Venue to read open interest from. An unsupported value falls back to bybit.
success (boolean)data (OpenInterest[])timestamp (integer)source (string) — The venue the open interest came from200 Open interest data402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected error, or the snapshot could not be fetched on a cold cache/api/v1/markets/listings$0.05 USDC per callReturns the latest new-listings delta for perpetual futures: the cross-exchange futures ticker set is diffed against the set of every futures symbol seen so far, and markets that newly appeared are returned as Ticker objects. The known set only grows, so a venue outage never makes its markets reappear as new; the very first call creates it and reports none. The result is cached for 1 hour, so concurrent callers see a stable answer; after that the known set grows and the next call produces the next delta.
The payload is nested one level deeper than most endpoints: data.data holds {newListings, totalCount, previousCount}, data.timestamp is when the snapshot was computed and data.cached whether it came from the 1-hour cache. The outer timestamp is the response time and the outer cached is always false.
($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)data (object)timestamp (integer) — Epoch ms of the responsecached (boolean) — Always false; see data.cached200 New listings402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/insights$0.05 USDC per callReturns the cross-exchange perpetual tickers with 24h quote volume ≥ $1M and 24h price change ≥ 1% — full Ticker objects, each with an optional fundingArb list of "exchange: rate%" strings — plus tickersCount and fundingArbCount. No query parameters are read. data.cached.futures reports whether the ticker set came from cache; the top-level cached is always false. ($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)data (object)timestamp (integer)cached (boolean) — Always false; see data.cached200 Screened tickers402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/news$0.05 USDC per callReturns up to 10 recent news items from the Alpha Vantage NEWS_SENTIMENT feed (topics: technology, IPO, earnings, financial markets), cached for 5 minutes: items: [{title, url, time_published, summary, source, impact_score, sentiment}]. time_published uses Alpha Vantage's YYYYMMDDTHHMMSS format; impact_score is the item's overall sentiment score × 100 (signed). ($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)items (NewsItem[])timestamp (integer)200 News feed402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/calendar$0.05 USDC per callMedium- and high-impact macro-economic events for this week and next — central-bank rate decisions, FOMC, CPI, NFP, GDP and more — from the Forex Factory calendar, sourced via x402node and cached for 24 hours: data: {events: [CalendarEvent], source, fromCache, fetchedAt, expiresAt, ageSeconds, truncated}. Events are keyed by the currency they move and include forecast, previous and (once released) actual values as published. Filters: currency (comma-separated codes; country is accepted as an alias), impact (exact level), search (case-insensitive substring of event) and from/to (UTC dates, inclusive). ($0.05 USDC on Solana mainnet)
currency (string)Comma-separated currency codes to keep (case-insensitive)
impact (string; one of Low, Medium, High)Exact impact level (case-insensitive)
search (string)Case-insensitive substring of event
from (string; date)Earliest UTC date, inclusive
to (string; date)Latest UTC date, inclusive
success (boolean)data (object)timestamp (integer)cached (boolean) — Same as data.fromCache200 Economic calendar events402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected error, or the calendar provider could not be paid or reached/api/v1/markets/swap-volume$0.05 USDC per callReturns up to 30 daily entries {date, volume, timestamp}. volume is the day's peak of the summed 24h volume (USD) across the venues in /api/v1/markets/volume-snapshot — perpetual venues, not DEX swaps, despite the route name. data is empty until history has been recorded. ($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)data (object[])200 Daily volume history402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/volume-snapshot$0.05 USDC per callReturns one entry per perpetual venue with its 24h snapshot: {exchange, displayName, chain, timestamp, totalVolume24h, totalOpenInterest, tvl?, markets[{symbol, volume24h, openInterest?, price, fundingRate?, priceChange24h?}], status, error?}. Only venues whose fetch succeeded are included. Cached for 60 seconds; when served from cache, timestamp is the last update. An optional top-level error string reports a degraded refresh. Use to rank venues by liquidity or track volume moving between them. Filter by exchange. ($0.05 USDC on Solana mainnet)
exchange (string)Only this venue (exact id, case-insensitive)
success (boolean)data (object[])cached (boolean)timestamp (integer)error (string) — Present when the refresh was degraded200 Volume data402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/quakes$0.05 USDC per callReturns the USGS "significant earthquakes, past day" GeoJSON feed unchanged: data: {type, metadata, features[], bbox?}, where each feature carries USGS properties (mag, place, time, tsunami, sig, …), geometry and id. It contains no market data. timestamp is when the server cached the feed, which can be older than the request. ($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)data (object)timestamp (integer)200 USGS significant-earthquake feed402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/markets/symbol-venues$0.05 USDC per callReturns which venues list each symbol: data.symbolVenues maps an upper-cased symbol to the sorted venue ids that offer a market for it. This is a listings index (does a venue offer the market), not a price aggregate — use it to find where a symbol trades before calling a venue-specific endpoint. Served from a 24-hour cache; data.updatedAt is the build time (epoch ms), data.venueCount the number of venues that contributed at least one symbol, and cached whether the call was served from that cache. ($0.05 USDC on Solana mainnet)
No query parameters.
success (boolean)data (object)timestamp (integer)cached (boolean)200 Symbol → venue membership map402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Unexpected server error/api/v1/solana-perps/long-short$0.05 USDC per callOpen-interest snapshot across Solana perpetual venues, collected server-side in one pass. rows holds venues that publish a genuine long-vs-short split ({venue, symbol, longUsd, shortUsd, longPositions, shortPositions} — the position counts are null whenever a venue publishes none, which is currently every venue); totals holds venues that publish combined open interest only ({venue, symbol, totalUsd}); venueStatus maps each venue id to ok or error, so a degraded source is visible instead of silently missing. fetchedAt is when the snapshot was assembled; the per-venue data behind it can be up to a minute older. ($0.05 USDC on Solana mainnet)
venues (string)Comma-separated venue ids (case-insensitive) that rows and totals are narrowed to. Omit for every venue; the valid ids are the keys of venueStatus.
fetchedAt (string)rows (object[])totals (object[])venueStatus (object)200 Long/short and total open-interest rows per venue and symbol402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Snapshot collection failedGET https://www.tetrac.xyz/api/v1/solana-perps/long-short?venues=pacifica/api/v1/solana-perps/pacifica-watchlist$0.05 USDC per callReturns the top Pacifica trader accounts ranked by current open-interest notional, trimmed to {address, label, oiUsd} each, plus totalRanked (accounts on the upstream leaderboard) and fetchedAt. label is null when the trader set no username or enabled privacy mode. Accounts with no open interest are left out, so accounts can be shorter than limit. Built for subscribing to those accounts on Pacifica's public WebSocket — this endpoint is address discovery only and carries no trade events itself. The upstream leaderboard is refreshed at most every 5 minutes; fetchedAt is the response time. ($0.05 USDC on Solana mainnet)
limit (integer; default 250 · min 1 · max 1000)Number of accounts to return (parsed as an integer). Values above the maximum are capped; a non-positive or unparseable value falls back to the default.
accounts (object[])totalRanked (integer)fetchedAt (string)200 Ranked account watchlist402 Payment required (x402)429 Rate limit exceeded — retry after Retry-After seconds500 Leaderboard fetch failedGET https://www.tetrac.xyz/api/v1/solana-perps/pacifica-watchlist?limit=250