Tetrac

Tetrac API Documentation

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.

Authentication

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.

Session token

  • Every sign-in returns authToken and publicKey. Send them on every authenticated request as the ttc-auth-token and ttc-public-key headers.
  • The token is valid for 24 hours from sign-in and is not refreshed. Signing in again issues a new token and revokes the previous one.
  • On a paid /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>
POST/api/auth/challenge

Issue a one-time challenge for a wallet or email sign-in, registration or connect-wallet call.

JSON body

  • 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.

Success: 200

{
  "challenge": "<64 hex characters>",
  "pbkdf2Iterations": 600000
}

Errors

  • 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.

POST/api/auth/login-wallet

Sign in with a registered Solana wallet.

JSON body

  • publicKey (string)required

    The wallet's Solana address (base58).

  • signature (string)required

    Hex-encoded ed25519 signature of the message below, made by that wallet (a 0x prefix is accepted).

  • challenge (string)required

    The challenge issued for this publicKey.

  • appId (string)

    Optional. Must be "tetrac" when sent; that is also the default.

Signed message (UTF-8)

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>

Success: 200

{
  "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
  "authToken": "<64 hex characters>",
  "user": {
    "appId": "tetrac",
    "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
    "authMethod": "wallet",
    "wallets": [
      {
        "chain": "evm",
        "role": "funds",
        "publicKey": "0x1234…",
        "encryptedSecret": "<ciphertext>"
      }
    ],
    "createdAt": 1760000000000
  }
}

Errors

  • 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.

POST/api/auth/connect-wallet

Sign in with a Solana wallet, creating the account on first use (login-or-register in one call).

JSON body

  • publicKey (string)required

    The wallet's Solana address (base58).

  • signature (string)required

    Hex-encoded ed25519 signature of the message below, made by that wallet.

  • challenge (string)required

    The 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.

Signed message (UTF-8)

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>

Success: 201

{
  "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
  "authToken": "<64 hex characters>",
  "user": {
    "appId": "tetrac",
    "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
    "authMethod": "wallet",
    "wallets": [
      {
        "chain": "evm",
        "role": "funds",
        "publicKey": "0x1234…",
        "encryptedSecret": "<ciphertext>"
      }
    ],
    "createdAt": 1760000000000
  }
}

Errors

  • 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.

POST/api/auth/register

Create an email, passkey or wallet account from a wallet bundle generated in the browser.

JSON body

  • publicKey (string)required

    Solana address (base58) of the account's funds wallet. The challenge must have been issued for it.

  • signature (string)required

    Hex-encoded ed25519 signature of the message below, made by that wallet's key.

  • challenge (string)required

    The 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.

Signed message (UTF-8)

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>

Success: 201

{
  "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
  "authToken": "<64 hex characters>",
  "user": {
    "appId": "tetrac",
    "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
    "authMethod": "wallet",
    "wallets": [
      {
        "chain": "evm",
        "role": "funds",
        "publicKey": "0x1234…",
        "encryptedSecret": "<ciphertext>"
      }
    ],
    "createdAt": 1760000000000
  }
}

Errors

  • 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.
POST/api/auth/login

Sign in to an email account.

JSON body

  • email (string)required

    The account email.

  • signature (string)required

    Hex-encoded ed25519 signature of the message below, made by the account's auth key (the key behind authPublicKey).

  • challenge (string)required

    The challenge issued for this email.

  • appId (string)

    Optional. Must be "tetrac" when sent; that is also the default.

Signed message (UTF-8)

Sign in to your TTC account: <challenge>

Success: 200

{
  "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
  "authToken": "<64 hex characters>",
  "user": {
    "appId": "tetrac",
    "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
    "authMethod": "email",
    "wallets": [
      {
        "chain": "evm",
        "role": "funds",
        "publicKey": "0x1234…",
        "encryptedSecret": "<ciphertext>"
      }
    ],
    "createdAt": 1760000000000
  }
}

Errors

  • 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.

POST/api/auth/logout

Revoke the current session.

Headers

  • ttc-auth-token (string)required

    The authToken from a sign-in response (64 hex characters, valid 24 h).

  • ttc-public-key (string)required

    The publicKey from the same sign-in response.

Success: 200

{
  "ok": true
}

Errors

  • 429 Rate limit exceeded.

Always answers 200 { ok: true }, whether or not the token was valid; a valid session is revoked.

GET/api/auth/user-data

Read the signed-in account's record.

Headers

  • ttc-auth-token (string)required

    The authToken from a sign-in response (64 hex characters, valid 24 h).

  • ttc-public-key (string)required

    The publicKey from the same sign-in response.

Success: 200

{
  "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
  }
}

Errors

  • 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.

POST/api/auth/user-data

Save one account preference.

Headers

  • ttc-auth-token (string)required

    The authToken from a sign-in response (64 hex characters, valid 24 h).

  • ttc-public-key (string)required

    The publicKey from the same sign-in response.

JSON body

  • preferenceKey (string)required

    "migration" or "user_participation_preferences".

  • preferences (object)required

    The value to store, at most 4 KB as JSON. user_participation_preferences must be { leaderboard: boolean, dao: boolean, lastUpdated: string }.

Success: 200

{
  "success": true,
  "message": "Preferences updated successfully"
}

Errors

  • 400 Unknown preferenceKey, a malformed value, or over 4 KB.
  • 401 Invalid or expired session.
  • 429 Rate limit exceeded.
POST/api/auth/import-wallet

Add or replace wallet slots on the signed-in account.

Headers

  • ttc-auth-token (string)required

    The authToken from a sign-in response (64 hex characters, valid 24 h).

  • ttc-public-key (string)required

    The publicKey from the same sign-in response.

JSON body

  • wallets (array)required

    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. Each entry replaces the slot it names.

Success: 200

{
  "user": {
    "appId": "tetrac",
    "publicKey": "CgzKjTLrNgi9B6iCzLKfcLasYTuuEUibsei97qjmm7t5",
    "authMethod": "wallet",
    "wallets": [
      {
        "chain": "evm",
        "role": "funds",
        "publicKey": "0x1234…",
        "encryptedSecret": "<ciphertext>"
      }
    ],
    "createdAt": 1760000000000
  }
}

Errors

  • 400 wallets is missing or malformed.
  • 401 Missing, invalid or expired session.
  • 429 Rate limit exceeded.
GET/api/auth/search-wallet

Check whether an account exists for a Solana address.

Query parameters

  • publicKey (string)required

    The Solana address (base58) to look up.

  • appId (string)

    Optional. Must be "tetrac" when sent; that is also the default.

Success: 200

{
  "exists": true
}

Errors

  • 400 publicKey is missing or malformed.
  • 429 Rate limit exceeded.

Pricing & errors

Prices

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.

EndpointNamePrice
GET /api/v1/marketsTetrac Markets IndexFree
GET /api/v1/markets/ttc-scannerTetrac Scanner$0.05 USDC
GET /api/v1/markets/ttc-scanner-cacheTetrac Scanner (All Markets)$0.50 USDC
GET /api/v1/markets/hybrid-tickersTetrac Hybrid Tickers$0.05 USDC
GET /api/v1/markets/funding-ratesTetrac Funding Rates$0.05 USDC
GET /api/v1/markets/open-interestTetrac Open Interest$0.05 USDC
GET /api/v1/exchangesTetrac Exchanges (Read)$0.05 USDC
POST /api/v1/exchangesTetrac Exchanges (Trade)$0.05 USDC
GET /api/v1/markets/listingsTetrac New Listings$0.05 USDC
GET /api/v1/markets/insightsTetrac Market Insights$0.05 USDC
GET /api/v1/markets/newsTetrac Market News$0.05 USDC
GET /api/v1/markets/calendarTetrac Economic Calendar$0.05 USDC
GET /api/v1/markets/swap-volumeTetrac Perp DEX Volume History$0.05 USDC
GET /api/v1/markets/volume-snapshotTetrac Volume Snapshot$0.05 USDC
GET /api/v1/markets/quakesTetrac Market Quakes$0.05 USDC
GET /api/v1/exchanges/latencyExchange Latency$0.05 USDC
GET /api/v1/markets/symbol-venuesTetrac Symbol Venues$0.05 USDC
GET /api/v1/solana-perps/long-shortTetrac Solana Perps Long/Short$0.05 USDC
GET /api/v1/solana-perps/pacifica-watchlistTetrac Pacifica Watchlist$0.05 USDC

Paying per request

  1. Call the endpoint with no session. The 402 body carries the x402 v2 challenge (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.
  2. Send that amount of USDC to payTo on Solana mainnet from your own wallet. You sign the transfer and pay its network fee; Tetrac never signs or sponsors it.
  3. Repeat the request with the receipt in one of two headers:
    • canonical x402 v2: 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.
    • v1 (still supported): x-x402-payment: x402:base64({signature, payer, amount}).
  4. A receipt works once (a 24-hour replay window) and the transfer must be under 5 minutes old. A bad parameter is refused with 400 and 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.

Status codes

  • 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.

Rate limits

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.

EndpointsFreePro (3×)Elite (10×)
/api/v1/exchanges, /api/v1/exchanges/latency20/min60/min200/min
Every other paid endpoint30/min90/min300/min

Exchange

GET/api/v1/exchanges$0.05 USDC per call

List exchange methods, pricing and venues

Exchange 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.

Response fields (200)

  • success (boolean)
  • status (string)
  • code (integer)
  • pricing (object)
  • methods (object) — Keyed by method name; every entry is run with POST /api/v1/exchanges
  • supportedExchanges (string[]) — Venue ids accepted as exchangeName by POST /api/v1/exchanges

Responses

  • 200 Methods catalog, pricing summary and venue roster
  • 400 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 supportedExchanges
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
POST/api/v1/exchanges$0.05 USDC per call

Run an exchange method: account reads and trading

Exchange 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):

  • Public market data, no credentials: getTickers, getBestBidAsk, getKlines, getContractSpecs
  • Account reads, apiKey + apiSecret: getBalance, getPositions, getOrders, getUserTradeHistory, getInfoLeverage, getDepositAddress
  • Propr onboarding, apiKey only: getAccounts
  • Trading and withdrawals, apiKey + apiSecret: placeMarketOrder, placeLimitOrder, placeStopOrder, cancelOrder, cancelAllOrders, closeAllPositions, setLeverage, setHedgeMode, createWithdrawal

Not 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 string
  • getBestBidAsk — {symbol}, or the bare symbol string
  • closeAllPositions — {}
  • 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)

JSON body

  • exchangeName (string)required

    Venue 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)required

    One 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

Response fields (200)

  • success (boolean)
  • data (any) — Method-shaped result
  • code (integer)
  • msg (string)
  • exchange (string)

Responses

  • 200 Method result
  • 400 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 supportedExchanges
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error

Example request

POST https://www.tetrac.xyz/api/v1/exchanges
{
  "exchangeName": "binance",
  "method": "getTickers",
  "params": {}
}
GET/api/v1/exchanges/latency$0.05 USDC per call

Fetch exchange reachability and latency

Probes 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.

Response fields (200)

  • summary (object) — Aggregate counts and mean latency, split per probe type
  • exchanges (ExchangeLatency[])
  • timestamp (integer) — Epoch ms when the probe run completed

Responses

  • 200 Per-exchange latency probe results plus aggregate summary
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Probe run failed

POST /api/v1/exchanges methods

The method values the dispatcher accepts, with the credentials each needs. Not every venue implements every method; an unimplemented one returns 400.

MethodDescriptionCredentials
setHedgeModeSet hedge mode for the exchange accountapiKey + apiSecret
setLeverageSet leverage for a specific trading pairapiKey + apiSecret
getInfoLeverageGet the leverage tier brackets for a specific trading pair (notional ranges and their max leverage caps)apiKey + apiSecret
getPositionsRetrieve current open positionsapiKey + apiSecret
getBalanceGet account balance informationapiKey + apiSecret
placeLimitOrderExecute a limit order (filled when price reaches specified level)apiKey + apiSecret
placeMarketOrderExecute a market order (filled immediately at current price)apiKey + apiSecret
placeStopOrderPlace a stop order that triggers at a specified priceapiKey + apiSecret
closeAllPositionsClose all open positions for the accountapiKey + apiSecret
createWithdrawalInitiate a withdrawal from the exchangeapiKey + apiSecret
getDepositAddressGet deposit address for a specific assetapiKey + apiSecret
getOrdersRetrieve open or historical ordersapiKey + apiSecret
cancelAllOrdersCancel all open orders for the accountapiKey + apiSecret
cancelOrderCancel a specific order by IDapiKey + apiSecret
getUserTradeHistoryRetrieve user's historical trade recordsapiKey + apiSecret
getAccountsList the user's Propr challenge-attempt accounts (onboarding account picker; Propr only)apiKey
getTickersGet current ticker information for trading pairsnone (public market data)
getBestBidAskGet best bid and ask prices for a trading pairnone (public market data)
getKlinesGet historical candlestick/kline data for a trading pairnone (public market data)
getContractSpecsGet per-market contract size, size increment and order minimums (canonical symbols)none (public market data)

Examples

Binance market order (session auth)

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.

Orderly positions

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.

Market Data

GET/api/v1/marketsFree

List market data endpoints and their prices

Free 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.

Response fields (200)

  • success (boolean)
  • status (string)
  • code (integer)
  • pricing (object)
  • methods (object) — Keyed by sub-route slug, e.g. funding-rates

Responses

  • 200 Endpoint catalog and pricing summary
  • 429 Rate limit exceeded — retry after Retry-After seconds
GET/api/v1/markets/ttc-scanner$0.05 USDC per call

Run the Tetrac technical scan for one symbol

Runs 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)

Query parameters

  • symbol (string)required

    Market 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.

Response fields (200)

  • success (boolean)
  • timestamp (integer)
  • params (object)
  • data (object)

Responses

  • 200 Scanner result with signal
  • 400 Missing or invalid query parameter, returned before any payment is taken
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected error, or fewer than 50 bars of history for the symbol (an unknown or newly listed market)

Example request

GET https://www.tetrac.xyz/api/v1/markets/ttc-scanner?symbol=BTCUSDT&timeframe=1h
GET/api/v1/markets/ttc-scanner-cache$0.50 USDC per call

Fetch the full-market Tetrac scanner snapshot

The 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)

Query parameters

  • 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.

Response fields (200)

  • success (boolean)
  • timestamp (integer)
  • generatedAt (integer) — Without full=1: epoch ms of the last sweep, null if none
  • staleAtMs (integer) — Epoch ms when the snapshot becomes eligible for a refresh, or null if none exists yet
  • data (object) — Only with full=1

Responses

  • 200 Snapshot freshness, or the full snapshot with ?full=1
  • 400 Invalid full value, returned before any payment is taken
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/hybrid-tickers$0.05 USDC per call

Fetch multi-exchange perpetual tickers

Returns 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)

Query parameters

  • 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.

Response fields (200)

  • success (boolean)
  • data (object)
  • timestamp (integer)
  • cached (boolean)
  • cacheInfo (object)
  • warning (string) — Optional advisory about the cache's state

Responses

  • 200 Perpetual tickers
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error

Example request

GET https://www.tetrac.xyz/api/v1/markets/hybrid-tickers?exchange=binance&minimumVolume=10000000
GET/api/v1/markets/funding-rates$0.05 USDC per call

Fetch perpetual funding rates across venues

Returns 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.

Query parameters

  • 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.

Response fields (200)

  • success (boolean)
  • data (FundingRate[])
  • cached (boolean)
  • timestamp (integer)
  • error (string) — Present when some venues failed during the refresh

Responses

  • 200 Funding rate data
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/open-interest$0.05 USDC per call

Fetch open interest by market from one venue

Returns 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)

Query parameters

  • source (string)

    Venue to read open interest from. An unsupported value falls back to bybit.

Response fields (200)

  • success (boolean)
  • data (OpenInterest[])
  • timestamp (integer)
  • source (string) — The venue the open interest came from

Responses

  • 200 Open interest data
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected error, or the snapshot could not be fetched on a cold cache
GET/api/v1/markets/listings$0.05 USDC per call

Fetch new perpetual futures listings

Returns 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.

Response fields (200)

  • success (boolean)
  • data (object)
  • timestamp (integer) — Epoch ms of the response
  • cached (boolean) — Always false; see data.cached

Responses

  • 200 New listings
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/insights$0.05 USDC per call

List momentum movers with funding context

Returns 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.

Response fields (200)

  • success (boolean)
  • data (object)
  • timestamp (integer)
  • cached (boolean) — Always false; see data.cached

Responses

  • 200 Screened tickers
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/news$0.05 USDC per call

Fetch recent financial market news

Returns 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.

Response fields (200)

  • success (boolean)
  • items (NewsItem[])
  • timestamp (integer)

Responses

  • 200 News feed
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/calendar$0.05 USDC per call

Fetch macro-economic calendar events

Medium- 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)

Query parameters

  • 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

Response fields (200)

  • success (boolean)
  • data (object)
  • timestamp (integer)
  • cached (boolean) — Same as data.fromCache

Responses

  • 200 Economic calendar events
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected error, or the calendar provider could not be paid or reached
GET/api/v1/markets/swap-volume$0.05 USDC per call

Fetch daily cross-venue volume history

Returns 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.

Response fields (200)

  • success (boolean)
  • data (object[])

Responses

  • 200 Daily volume history
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/volume-snapshot$0.05 USDC per call

Fetch a cross-exchange volume snapshot

Returns 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)

Query parameters

  • exchange (string)

    Only this venue (exact id, case-insensitive)

Response fields (200)

  • success (boolean)
  • data (object[])
  • cached (boolean)
  • timestamp (integer)
  • error (string) — Present when the refresh was degraded

Responses

  • 200 Volume data
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/quakes$0.05 USDC per call

Fetch significant earthquakes from USGS

Returns 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.

Response fields (200)

  • success (boolean)
  • data (object)
  • timestamp (integer)

Responses

  • 200 USGS significant-earthquake feed
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error
GET/api/v1/markets/symbol-venues$0.05 USDC per call

List which exchanges quote a given symbol

Returns 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.

Response fields (200)

  • success (boolean)
  • data (object)
  • timestamp (integer)
  • cached (boolean)

Responses

  • 200 Symbol → venue membership map
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Unexpected server error

Solana Perps

GET/api/v1/solana-perps/long-short$0.05 USDC per call

Fetch Solana perp long/short OI ratios

Open-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)

Query parameters

  • 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.

Response fields (200)

  • fetchedAt (string)
  • rows (object[])
  • totals (object[])
  • venueStatus (object)

Responses

  • 200 Long/short and total open-interest rows per venue and symbol
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Snapshot collection failed

Example request

GET https://www.tetrac.xyz/api/v1/solana-perps/long-short?venues=pacifica
GET/api/v1/solana-perps/pacifica-watchlist$0.05 USDC per call

List Pacifica top open-interest accounts

Returns 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)

Query parameters

  • 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.

Response fields (200)

  • accounts (object[])
  • totalRanked (integer)
  • fetchedAt (string)

Responses

  • 200 Ranked account watchlist
  • 402 Payment required (x402)
  • 429 Rate limit exceeded — retry after Retry-After seconds
  • 500 Leaderboard fetch failed

Example request

GET https://www.tetrac.xyz/api/v1/solana-perps/pacifica-watchlist?limit=250