{
  "openapi": "3.0.3",
  "info": {
    "title": "Tetrac Trading API",
    "description": "Multi-exchange trading data API \u2014 tickers, funding rates, open interest,\ntechnical analysis (Tetrac scanner), news, economic calendar, market\nintelligence, volume data, and order execution. Market data covers\n30+ CEXs and DEXs; order execution covers 40+ CEXs and DEXs.\n\n## Authentication\n\nEvery endpoint except the free `/api/v1/markets` discovery index requires one of:\n\n- **Session auth** \u2014 pass `ttc-auth-token` (Bearer) + `ttc-public-key` header for registered Tetrac users.\n- **x402 micropayment** \u2014 pass a signed Solana USDC payment ($0.05 standard, $0.50 for the full-market scanner snapshot) in the `x-x402-payment` header.\n  See [x402.json](https://www.tetrac.xyz/.well-known/x402.json) for payment details.\n",
    "version": "1.0.0",
    "contact": {
      "name": "Tetrac",
      "url": "https://t.me/tetracChat"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://www.tetrac.xyz",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/v1/markets": {
      "get": {
        "operationId": "getMarketsIndex",
        "summary": "List market data endpoints and their prices",
        "description": "Free discovery index for every `/api/v1/markets/*` endpoint \u2014 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)\n",
        "responses": {
          "200": {
            "description": "Endpoint catalog and pricing summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "example": "ok"
                    },
                    "code": {
                      "type": "integer",
                      "example": 200
                    },
                    "pricing": {
                      "type": "object",
                      "properties": {
                        "amount": {
                          "type": "string",
                          "example": "0.05"
                        },
                        "currency": {
                          "type": "string",
                          "example": "USDC"
                        },
                        "network": {
                          "type": "string",
                          "example": "Solana"
                        },
                        "per": {
                          "type": "string",
                          "example": "request"
                        }
                      }
                    },
                    "methods": {
                      "type": "object",
                      "description": "Keyed by sub-route slug, e.g. `funding-rates`",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "method": {
                            "description": "HTTP method, or an array when the endpoint accepts several",
                            "oneOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              }
                            ]
                          },
                          "description": {
                            "type": "string"
                          },
                          "price": {
                            "type": "object",
                            "properties": {
                              "amount": {
                                "type": "string"
                              },
                              "currency": {
                                "type": "string"
                              }
                            }
                          },
                          "params": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "description": {
                                  "type": "string"
                                },
                                "required": {
                                  "type": "boolean"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          }
        },
        "tags": [
          "Market Data"
        ],
        "security": []
      }
    },
    "/api/v1/markets/hybrid-tickers": {
      "get": {
        "operationId": "getHybridTickers",
        "summary": "Fetch multi-exchange perpetual tickers",
        "description": "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)\n",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "description": "Market type. Only `futures` is served; any other value is ignored and futures are returned.",
            "schema": {
              "type": "string",
              "example": "futures"
            }
          },
          {
            "name": "symbol",
            "in": "query",
            "description": "Exact symbol match (upper-cased before comparing).",
            "schema": {
              "type": "string",
              "example": "BTCUSDT"
            }
          },
          {
            "name": "exchange",
            "in": "query",
            "description": "Keep only markets listed on this venue (matched against `source` and `sources`, case-insensitive).",
            "schema": {
              "type": "string",
              "example": "binance"
            }
          },
          {
            "name": "minimumVolume",
            "in": "query",
            "description": "Minimum 24h quote volume in USD (`quoteVolume`).",
            "schema": {
              "type": "number",
              "minimum": 0,
              "example": 10000000
            }
          },
          {
            "name": "minimumPrice",
            "in": "query",
            "description": "Minimum `lastPrice`. Swapped with `maximumPrice` if it is the larger of the two.",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          },
          {
            "name": "maximumPrice",
            "in": "query",
            "description": "Maximum `lastPrice`.",
            "schema": {
              "type": "number",
              "minimum": 0
            }
          },
          {
            "name": "up",
            "in": "query",
            "description": "Keep markets whose 24h `priceChangePercent` is at least this value.",
            "schema": {
              "type": "number",
              "minimum": -100,
              "maximum": 10000
            }
          },
          {
            "name": "down",
            "in": "query",
            "description": "Keep markets down at least this many percent over 24h.",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "health",
            "in": "query",
            "description": "Any value: return `data` = `{status, redis, lastError, lastSuccessfulFetch, timeSinceLastFetch}` (the ticker cache's health) instead of tickers.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Perpetual tickers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "futures": {
                          "type": "object",
                          "properties": {
                            "data": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Ticker"
                              }
                            }
                          }
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "cached": {
                      "type": "boolean"
                    },
                    "cacheInfo": {
                      "type": "object",
                      "properties": {
                        "futures": {
                          "type": "boolean"
                        }
                      }
                    },
                    "warning": {
                      "type": "string",
                      "description": "Optional advisory about the cache's state"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/funding-rates": {
      "get": {
        "operationId": "getFundingRates",
        "summary": "Fetch perpetual funding rates across venues",
        "description": "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)\n\n**Comparing venues:** `fundingRate` is each venue's NATIVE per-interval rate, and that interval differs per MARKET \u2014 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.\n\n`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.\n",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "description": "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.",
            "schema": {
              "type": "string",
              "example": "BTCUSDT"
            }
          },
          {
            "name": "exchange",
            "in": "query",
            "description": "Comma-separated venue ids to keep (case-insensitive).",
            "schema": {
              "type": "string",
              "example": "binance,bybit"
            }
          },
          {
            "name": "arb",
            "in": "query",
            "description": "Return only the N highest and N lowest `fundingRate` rows, sorted by `fundingRate` descending.",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Funding rate data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/FundingRate"
                      }
                    },
                    "cached": {
                      "type": "boolean"
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when some venues failed during the refresh"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/open-interest": {
      "get": {
        "operationId": "getOpenInterest",
        "summary": "Fetch open interest by market from one venue",
        "description": "Returns the latest open-interest snapshot from one venue \u2014 chosen by `source`, default `bybit` \u2014 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)\n",
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "description": "Venue to read open interest from. An unsupported value falls back to `bybit`.",
            "schema": {
              "type": "string",
              "example": "bybit"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Open interest data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/OpenInterest"
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "source": {
                      "type": "string",
                      "description": "The venue the open interest came from"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected error, or the snapshot could not be fetched on a cold cache"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/listings": {
      "get": {
        "operationId": "getNewListings",
        "summary": "Fetch new perpetual futures listings",
        "description": "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.\n\nThe 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`.\n\n($0.05 USDC on Solana mainnet)\n",
        "responses": {
          "200": {
            "description": "New listings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "newListings": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Ticker"
                              }
                            },
                            "totalCount": {
                              "type": "integer",
                              "description": "Futures symbols currently tracked"
                            },
                            "previousCount": {
                              "type": "integer",
                              "description": "Size of the known-symbols set before this snapshot"
                            }
                          }
                        },
                        "timestamp": {
                          "type": "integer",
                          "description": "Epoch ms when the snapshot was computed"
                        },
                        "cached": {
                          "type": "boolean",
                          "description": "True if served from the 1-hour snapshot cache"
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer",
                      "description": "Epoch ms of the response"
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "Always false; see data.cached"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/volume-snapshot": {
      "get": {
        "operationId": "getVolumeSnapshot",
        "summary": "Fetch a cross-exchange volume snapshot",
        "description": "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)\n",
        "parameters": [
          {
            "name": "exchange",
            "in": "query",
            "description": "Only this venue (exact id, case-insensitive)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Volume data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "exchange": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "chain": {
                            "type": "string"
                          },
                          "timestamp": {
                            "type": "integer"
                          },
                          "totalVolume24h": {
                            "type": "number"
                          },
                          "totalOpenInterest": {
                            "type": "number"
                          },
                          "tvl": {
                            "type": "number"
                          },
                          "markets": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "symbol": {
                                  "type": "string"
                                },
                                "volume24h": {
                                  "type": "number"
                                },
                                "openInterest": {
                                  "type": "number"
                                },
                                "price": {
                                  "type": "number"
                                },
                                "fundingRate": {
                                  "type": "number"
                                },
                                "priceChange24h": {
                                  "type": "number"
                                }
                              }
                            }
                          },
                          "status": {
                            "type": "string"
                          },
                          "error": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "cached": {
                      "type": "boolean"
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when the refresh was degraded"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/swap-volume": {
      "get": {
        "operationId": "getSwapVolume",
        "summary": "Fetch daily cross-venue volume history",
        "description": "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` \u2014 perpetual venues, not DEX swaps, despite the route name. `data` is empty until history has been recorded. ($0.05 USDC on Solana mainnet)\n",
        "responses": {
          "200": {
            "description": "Daily volume history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string"
                          },
                          "volume": {
                            "type": "number"
                          },
                          "timestamp": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/symbol-venues": {
      "get": {
        "operationId": "getSymbolVenues",
        "summary": "List which exchanges quote a given symbol",
        "description": "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 \u2014 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)\n",
        "responses": {
          "200": {
            "description": "Symbol \u2192 venue membership map",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "symbolVenues": {
                          "type": "object",
                          "additionalProperties": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        },
                        "updatedAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "venueCount": {
                          "type": "integer"
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "cached": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/markets/ttc-scanner": {
      "get": {
        "operationId": "runTTCScanner",
        "summary": "Run the Tetrac technical scan for one symbol",
        "description": "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)\n",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "description": "Market symbol",
            "schema": {
              "type": "string",
              "example": "BTCUSDT"
            }
          },
          {
            "name": "timeframe",
            "in": "query",
            "description": "Binance USD\u24c8-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.",
            "schema": {
              "type": "string",
              "default": "1h",
              "example": "1h",
              "enum": [
                "1m",
                "3m",
                "5m",
                "15m",
                "30m",
                "1h",
                "2h",
                "4h",
                "6h",
                "8h",
                "12h",
                "1d",
                "3d",
                "1w",
                "1M"
              ]
            }
          },
          {
            "name": "bars",
            "in": "query",
            "description": "Number of historical bars to analyze, from 50. Defaults to 1000; larger values are clamped to 1000. Any other value returns 400 before payment.",
            "schema": {
              "type": "integer",
              "default": 1000,
              "maximum": 1000,
              "minimum": 50
            }
          },
          {
            "name": "swingStrength",
            "in": "query",
            "description": "Pivot sensitivity in bars, 1 to 100; higher values report only larger swings. Defaults to 10. Any other value returns 400 before payment.",
            "schema": {
              "type": "integer",
              "default": 10,
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scanner result with signal",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "params": {
                      "type": "object",
                      "properties": {
                        "symbol": {
                          "type": "string"
                        },
                        "timeframe": {
                          "type": "string"
                        },
                        "bars": {
                          "type": "integer"
                        },
                        "swingStrength": {
                          "type": "integer"
                        }
                      }
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "symbol": {
                          "type": "string"
                        },
                        "price": {
                          "type": "number"
                        },
                        "scans": {
                          "type": "array",
                          "description": "One scan per timeframe: pivot, fan angles, zone, momentum and per-side risk/reward",
                          "items": {
                            "type": "object"
                          }
                        },
                        "scoring": {
                          "type": "object",
                          "description": "Long and short fan-line scores, the pivots they are measured from, and `preferredDirection`"
                        },
                        "signal": {
                          "$ref": "#/components/schemas/ScannerSignal"
                        },
                        "breakout": {
                          "$ref": "#/components/schemas/BreakoutSignal"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid query parameter, returned before any payment is taken"
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected error, or fewer than 50 bars of history for the symbol (an unknown or newly listed market)"
          }
        },
        "tags": [
          "Technical Analysis"
        ]
      }
    },
    "/api/v1/markets/ttc-scanner-cache": {
      "get": {
        "operationId": "getTTCScannerCache",
        "summary": "Fetch the full-market Tetrac scanner snapshot",
        "description": "The latest cached technical-analysis signals for every scanned market. Without parameters it returns only the snapshot's freshness \u2014 `generatedAt` and `staleAtMs` (epoch ms; `generatedAt` is `null` before the first sweep) \u2014 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.\n\nThe 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)\n",
        "parameters": [
          {
            "name": "full",
            "in": "query",
            "description": "`1` returns the full snapshot in `data`; `0` or omitted returns the freshness fields only. Any other value returns 400 before payment.",
            "schema": {
              "type": "string",
              "example": "1",
              "enum": [
                "0",
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Snapshot freshness, or the full snapshot with ?full=1",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "generatedAt": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Without full=1: epoch ms of the last sweep, null if none"
                    },
                    "staleAtMs": {
                      "type": "integer",
                      "nullable": true,
                      "description": "Epoch ms when the snapshot becomes eligible for a refresh, or null if none exists yet"
                    },
                    "data": {
                      "type": "object",
                      "description": "Only with full=1",
                      "properties": {
                        "generatedAt": {
                          "type": "integer",
                          "nullable": true
                        },
                        "universe": {
                          "type": "string",
                          "example": "binance-futures"
                        },
                        "symbols": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "symbol": {
                                "type": "string"
                              },
                              "quoteVolume": {
                                "type": "number"
                              },
                              "signal": {
                                "$ref": "#/components/schemas/ScannerSignal"
                              },
                              "breakout": {
                                "$ref": "#/components/schemas/BreakoutSignal"
                              }
                            }
                          }
                        },
                        "meta": {
                          "type": "object",
                          "properties": {
                            "universeSize": {
                              "type": "integer"
                            },
                            "scanned": {
                              "type": "integer"
                            },
                            "skipped": {
                              "type": "integer"
                            },
                            "durationMs": {
                              "type": "integer"
                            },
                            "submitted": {
                              "type": "integer"
                            },
                            "dropped": {
                              "type": "integer"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid `full` value, returned before any payment is taken"
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Technical Analysis"
        ]
      }
    },
    "/api/v1/markets/news": {
      "get": {
        "operationId": "getCryptoNews",
        "summary": "Fetch recent financial market news",
        "description": "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 \u00d7 100 (signed). ($0.05 USDC on Solana mainnet)\n",
        "responses": {
          "200": {
            "description": "News feed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NewsItem"
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Intelligence"
        ]
      }
    },
    "/api/v1/markets/insights": {
      "get": {
        "operationId": "getMarketInsights",
        "summary": "List momentum movers with funding context",
        "description": "Returns the cross-exchange perpetual tickers with 24h quote volume \u2265 $1M and 24h price change \u2265 1% \u2014 full `Ticker` objects, each with an optional `fundingArb` list of `\"exchange: rate%\"` strings \u2014 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)\n",
        "responses": {
          "200": {
            "description": "Screened tickers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "tickers": {
                          "type": "array",
                          "items": {
                            "allOf": [
                              {
                                "$ref": "#/components/schemas/Ticker"
                              },
                              {
                                "type": "object",
                                "properties": {
                                  "fundingArb": {
                                    "type": "array",
                                    "description": "\"exchange: rate%\" entries",
                                    "items": {
                                      "type": "string"
                                    }
                                  }
                                }
                              }
                            ]
                          }
                        },
                        "tickersCount": {
                          "type": "integer"
                        },
                        "fundingArbCount": {
                          "type": "integer"
                        },
                        "cached": {
                          "type": "object",
                          "properties": {
                            "futures": {
                              "type": "boolean"
                            }
                          }
                        },
                        "timestamp": {
                          "type": "integer"
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "Always false; see data.cached"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Intelligence"
        ]
      }
    },
    "/api/v1/markets/calendar": {
      "get": {
        "operationId": "getEconomicCalendar",
        "summary": "Fetch macro-economic calendar events",
        "description": "Medium- and high-impact macro-economic events for this week and next \u2014 central-bank rate decisions, FOMC, CPI, NFP, GDP and more \u2014 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)\n",
        "parameters": [
          {
            "name": "currency",
            "in": "query",
            "description": "Comma-separated currency codes to keep (case-insensitive)",
            "schema": {
              "type": "string",
              "example": "USD,EUR"
            }
          },
          {
            "name": "impact",
            "in": "query",
            "description": "Exact impact level (case-insensitive)",
            "schema": {
              "type": "string",
              "enum": [
                "Low",
                "Medium",
                "High"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Case-insensitive substring of `event`",
            "schema": {
              "type": "string",
              "example": "CPI"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Earliest UTC date, inclusive",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-01"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Latest UTC date, inclusive",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-10-09"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Economic calendar events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "events": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CalendarEvent"
                          }
                        },
                        "source": {
                          "type": "string",
                          "example": "x402node"
                        },
                        "fromCache": {
                          "type": "boolean",
                          "description": "True when served from the 24-hour snapshot"
                        },
                        "fetchedAt": {
                          "type": "integer",
                          "format": "int64",
                          "description": "Epoch ms the snapshot was fetched"
                        },
                        "expiresAt": {
                          "type": "integer",
                          "format": "int64",
                          "description": "Epoch ms the 24-hour snapshot expires"
                        },
                        "ageSeconds": {
                          "type": "integer",
                          "description": "Snapshot age at response time"
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "True when the provider returned its full page, so more events may exist"
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "Same as data.fromCache"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected error, or the calendar provider could not be paid or reached"
          }
        },
        "tags": [
          "Market Intelligence"
        ]
      }
    },
    "/api/v1/markets/quakes": {
      "get": {
        "operationId": "getMarketQuakes",
        "summary": "Fetch significant earthquakes from USGS",
        "description": "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`, \u2026), `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)\n",
        "responses": {
          "200": {
            "description": "USGS significant-earthquake feed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "type": {
                          "type": "string",
                          "example": "FeatureCollection"
                        },
                        "metadata": {
                          "type": "object"
                        },
                        "features": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        },
                        "bbox": {
                          "type": "array",
                          "items": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "timestamp": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Market Intelligence"
        ]
      }
    },
    "/api/v1/solana-perps/long-short": {
      "get": {
        "operationId": "getSolanaPerpsLongShort",
        "summary": "Fetch Solana perp long/short OI ratios",
        "description": "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}` \u2014 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)\n",
        "parameters": [
          {
            "name": "venues",
            "in": "query",
            "required": false,
            "description": "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`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Long/short and total open-interest rows per venue and symbol",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "fetchedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "venue": {
                            "type": "string"
                          },
                          "symbol": {
                            "type": "string"
                          },
                          "longUsd": {
                            "type": "number"
                          },
                          "shortUsd": {
                            "type": "number"
                          },
                          "longPositions": {
                            "type": "integer",
                            "nullable": true
                          },
                          "shortPositions": {
                            "type": "integer",
                            "nullable": true
                          }
                        }
                      }
                    },
                    "totals": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "venue": {
                            "type": "string"
                          },
                          "symbol": {
                            "type": "string"
                          },
                          "totalUsd": {
                            "type": "number",
                            "nullable": true
                          }
                        }
                      }
                    },
                    "venueStatus": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string",
                        "enum": [
                          "ok",
                          "error"
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Snapshot collection failed"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/solana-perps/pacifica-watchlist": {
      "get": {
        "operationId": "getPacificaWatchlist",
        "summary": "List Pacifica top open-interest accounts",
        "description": "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 \u2014 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)\n",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "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.",
            "schema": {
              "type": "integer",
              "default": 250,
              "minimum": 1,
              "maximum": 1000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked account watchlist",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accounts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "address": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string",
                            "nullable": true
                          },
                          "oiUsd": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "totalRanked": {
                      "type": "integer"
                    },
                    "fetchedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Leaderboard fetch failed"
          }
        },
        "tags": [
          "Market Data"
        ]
      }
    },
    "/api/v1/exchanges": {
      "get": {
        "operationId": "getExchangeData",
        "summary": "List exchange methods, pricing and venues",
        "description": "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.\n\nEvery call that targets a venue \u2014 account reads and trading alike \u2014 goes to `POST /api/v1/exchanges`, which carries exchange credentials in the request body. This GET never reads credentials \u2014 secrets in a query string leak into access logs, proxy logs and referrer headers \u2014 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).\n\nAn 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.\n\nReturns `{success, status, code, pricing, methods, supportedExchanges}`. ($0.05 USDC on Solana mainnet)\n",
        "responses": {
          "200": {
            "description": "Methods catalog, pricing summary and venue roster",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "example": "ok"
                    },
                    "code": {
                      "type": "integer",
                      "example": 200
                    },
                    "pricing": {
                      "type": "object",
                      "properties": {
                        "amount": {
                          "type": "string",
                          "example": "0.05"
                        },
                        "currency": {
                          "type": "string",
                          "example": "USDC"
                        },
                        "network": {
                          "type": "string",
                          "example": "Solana"
                        },
                        "per": {
                          "type": "string",
                          "example": "request"
                        }
                      }
                    },
                    "methods": {
                      "type": "object",
                      "description": "Keyed by method name; every entry is run with `POST /api/v1/exchanges`",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string",
                            "example": "/api/v1/exchanges"
                          },
                          "method": {
                            "type": "string",
                            "example": "POST"
                          },
                          "description": {
                            "type": "string"
                          },
                          "price": {
                            "type": "object",
                            "properties": {
                              "amount": {
                                "type": "string"
                              },
                              "currency": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    },
                    "supportedExchanges": {
                      "type": "array",
                      "description": "Venue ids accepted as `exchangeName` by `POST /api/v1/exchanges`",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A non-empty `method` query parameter was sent \u2014 this GET takes none; run methods with `POST /api/v1/exchanges`. Returned before any payment is taken."
          },
          "402": {
            "description": "Payment required (x402) \u2014 the body also carries `methods`, `pricing` and `supportedExchanges`"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Exchange Infrastructure"
        ]
      },
      "post": {
        "operationId": "executeExchangeAction",
        "summary": "Run an exchange method: account reads and trading",
        "description": "Exchange dispatcher \u2014 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`).\n\n**IMPORTANT**: trading methods execute REAL trades with REAL money. Always confirm parameters with the user before calling.\n\nMethods and the credentials each needs (live descriptions: the `methods` catalog from `GET /api/v1/exchanges`):\n  - Public market data, no `credentials`: `getTickers`, `getBestBidAsk`, `getKlines`, `getContractSpecs`\n  - Account reads, `apiKey` + `apiSecret`: `getBalance`, `getPositions`, `getOrders`, `getUserTradeHistory`, `getInfoLeverage`, `getDepositAddress`\n  - Propr onboarding, `apiKey` only: `getAccounts`\n  - Trading and withdrawals, `apiKey` + `apiSecret`: `placeMarketOrder`, `placeLimitOrder`, `placeStopOrder`, `cancelOrder`, `cancelAllOrders`, `closeAllPositions`, `setLeverage`, `setHedgeMode`, `createWithdrawal`\n\nNot 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.\n\n`params` shape (varies by method):\n  - `placeMarketOrder` \u2014 `{symbol, side, quantity, reduceOnly?}`\n  - `placeLimitOrder` \u2014 `{symbol, side, quantity, price, timeInForce?, reduceOnly?}`\n  - `placeStopOrder` \u2014 `{symbol, side, quantity, stopPrice, ...}`\n  - `cancelOrder` \u2014 `{symbol, orderID, origClientOrderId?}`\n  - `cancelAllOrders`, `getOrders` \u2014 `{symbol?}`, or the bare symbol string\n  - `getBestBidAsk` \u2014 `{symbol}`, or the bare symbol string\n  - `closeAllPositions` \u2014 `{}`\n  - `setLeverage` \u2014 `{symbol, leverage}`\n  - `setHedgeMode` \u2014 `{symbol, isHedged}`\n  - `createWithdrawal` \u2014 `{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 \u2014 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).\n\nReturns `{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)\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "exchangeName": {
                    "type": "string",
                    "example": "binance",
                    "description": "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": {
                    "type": "string",
                    "description": "One of the methods in the `methods` catalog from `GET /api/v1/exchanges`",
                    "enum": [
                      "setHedgeMode",
                      "setLeverage",
                      "getInfoLeverage",
                      "getPositions",
                      "getBalance",
                      "placeLimitOrder",
                      "placeMarketOrder",
                      "placeStopOrder",
                      "closeAllPositions",
                      "createWithdrawal",
                      "getDepositAddress",
                      "getOrders",
                      "cancelAllOrders",
                      "cancelOrder",
                      "getUserTradeHistory",
                      "getAccounts",
                      "getTickers",
                      "getBestBidAsk",
                      "getKlines",
                      "getContractSpecs"
                    ]
                  },
                  "params": {
                    "description": "Method-specific parameters. `getOrders`, `getBestBidAsk` and `cancelAllOrders` also accept the bare symbol string.",
                    "oneOf": [
                      {
                        "type": "object"
                      },
                      {
                        "type": "string"
                      }
                    ]
                  },
                  "credentials": {
                    "description": "Exchange API credentials. Omit for the public market-data methods; `getAccounts` needs `apiKey` only; every other method needs `apiKey` and `apiSecret`.",
                    "type": "object",
                    "properties": {
                      "apiKey": {
                        "type": "string"
                      },
                      "apiSecret": {
                        "type": "string"
                      },
                      "passphrase": {
                        "type": "string"
                      },
                      "walletAddress": {
                        "type": "string",
                        "description": "Venue wallet address, for venues that key accounts by wallet"
                      }
                    }
                  }
                },
                "required": [
                  "exchangeName",
                  "method"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Method result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "description": "Method-shaped result"
                    },
                    "code": {
                      "type": "integer"
                    },
                    "msg": {
                      "type": "string"
                    },
                    "exchange": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "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": {
            "description": "Payment required (x402) \u2014 the body also carries `methods`, `pricing` and `supportedExchanges`"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Unexpected server error"
          }
        },
        "tags": [
          "Exchange Infrastructure"
        ]
      }
    },
    "/api/v1/exchanges/latency": {
      "get": {
        "operationId": "getExchangeLatency",
        "summary": "Fetch exchange reachability and latency",
        "description": "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 \u2014 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)\n",
        "responses": {
          "200": {
            "description": "Per-exchange latency probe results plus aggregate summary",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "summary": {
                      "type": "object",
                      "description": "Aggregate counts and mean latency, split per probe type",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "description": "Number of exchanges probed"
                        },
                        "tls": {
                          "$ref": "#/components/schemas/LatencyProbeSummary"
                        },
                        "data": {
                          "$ref": "#/components/schemas/LatencyProbeSummary"
                        }
                      }
                    },
                    "exchanges": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ExchangeLatency"
                      }
                    },
                    "timestamp": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Epoch ms when the probe run completed"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required (x402)"
          },
          "429": {
            "description": "Rate limit exceeded \u2014 retry after `Retry-After` seconds"
          },
          "500": {
            "description": "Probe run failed"
          }
        },
        "tags": [
          "Exchange Infrastructure"
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "integer"
          }
        }
      },
      "Ticker": {
        "type": "object",
        "description": "Binance-style 24h ticker for one perpetual market; numeric values are decimal strings",
        "properties": {
          "symbol": {
            "type": "string",
            "example": "BTCUSDT"
          },
          "source": {
            "type": "string",
            "description": "Primary venue for this row",
            "example": "binance"
          },
          "sources": {
            "type": "array",
            "description": "Every venue that lists this market",
            "items": {
              "type": "string"
            }
          },
          "priceChange": {
            "type": "string"
          },
          "priceChangePercent": {
            "type": "string",
            "example": "2.30"
          },
          "weightedAvgPrice": {
            "type": "string"
          },
          "prevClosePrice": {
            "type": "string"
          },
          "lastPrice": {
            "type": "string",
            "example": "67420.5"
          },
          "lastQty": {
            "type": "string"
          },
          "bidPrice": {
            "type": "string"
          },
          "bidQty": {
            "type": "string"
          },
          "askPrice": {
            "type": "string"
          },
          "askQty": {
            "type": "string"
          },
          "openPrice": {
            "type": "string"
          },
          "highPrice": {
            "type": "string"
          },
          "lowPrice": {
            "type": "string"
          },
          "volume": {
            "type": "string"
          },
          "quoteVolume": {
            "type": "string",
            "description": "24h quote volume (USD)"
          },
          "volumeByExchange": {
            "type": "object",
            "description": "24h volume split by venue"
          },
          "totalQuoteVolume": {
            "type": "string"
          },
          "openTime": {
            "type": "string"
          },
          "closeTime": {
            "type": "string"
          },
          "openInterest": {
            "type": "string"
          },
          "funding": {
            "type": "string"
          },
          "nextFunding": {
            "type": "string"
          },
          "firstId": {
            "type": "string"
          },
          "lastId": {
            "type": "string"
          },
          "count": {
            "type": "string"
          }
        }
      },
      "FundingRate": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string",
            "example": "BTCUSDT"
          },
          "exchange": {
            "type": "string",
            "example": "binance"
          },
          "fundingRate": {
            "type": "number",
            "description": "The venue's NATIVE rate for one settlement interval, as a decimal fraction (0.0001 = 0.01%). NOT comparable across rows \u2014 see hourlyRate.",
            "example": 0.0001
          },
          "intervalHours": {
            "type": "number",
            "description": "This market's settlement interval in hours. Omitted when it could not be established.",
            "example": 8
          },
          "intervalSource": {
            "type": "string",
            "enum": [
              "api-field",
              "api-derived",
              "venue-constant",
              "unknown"
            ],
            "description": "How intervalHours was determined. Always present; \"unknown\" means the rate is un-normalized and hourlyRate/dailyRoi are absent.",
            "example": "api-field"
          },
          "hourlyRate": {
            "type": "number",
            "description": "fundingRate normalized to a 1-hour basis. The cross-venue comparable. Omitted when intervalHours is unknown.",
            "example": 1.25e-05
          },
          "dailyRoi": {
            "type": "number",
            "description": "hourlyRate x 24 \u2014 a hypothetical 24h projection, not compounded. Omitted when hourlyRate is.",
            "example": 0.0003
          },
          "nextFundingTime": {
            "type": "integer",
            "format": "int64",
            "description": "Epoch milliseconds of the next settlement.",
            "example": 1785859200000
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Epoch ms of the reading"
          },
          "openInterest": {
            "type": "number",
            "description": "Open interest, when the venue reports it"
          }
        }
      },
      "OpenInterest": {
        "type": "object",
        "properties": {
          "symbol": {
            "type": "string",
            "example": "BTCUSDT"
          },
          "openInterest": {
            "type": "string",
            "description": "Open interest in base units (3 decimals)",
            "example": "12500.125"
          },
          "openInterestUsd": {
            "type": "string",
            "description": "Open interest in USD (2 decimals)",
            "example": "842000000.00"
          },
          "price": {
            "type": "string",
            "example": "67420.5"
          },
          "volumeUsd": {
            "type": "string",
            "description": "24h volume in USD (2 decimals)",
            "example": "800000000.00"
          },
          "timestamp": {
            "type": "integer",
            "example": 1711670400000
          }
        }
      },
      "NewsItem": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "time_published": {
            "type": "string",
            "description": "Alpha Vantage YYYYMMDDTHHMMSS format",
            "example": "20260929T131500"
          },
          "summary": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "impact_score": {
            "type": "number",
            "description": "Overall sentiment score \u00d7 100 (signed)",
            "example": 12.5
          },
          "sentiment": {
            "type": "string",
            "enum": [
              "Positive",
              "Negative",
              "Neutral"
            ]
          }
        }
      },
      "CalendarEvent": {
        "type": "object",
        "description": "One economic event, normalized from the Forex Factory calendar",
        "properties": {
          "date": {
            "type": "string",
            "format": "date-time",
            "description": "Scheduled release time, UTC",
            "example": "2026-10-02T12:30:00.000Z"
          },
          "country": {
            "type": "string",
            "description": "The currency the event moves (the provider keys events by currency)",
            "example": "USD"
          },
          "event": {
            "type": "string",
            "example": "Non-Farm Employment Change"
          },
          "currency": {
            "type": "string",
            "description": "Same code as `country`",
            "example": "USD"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "description": "Last published value, as displayed (unit included)",
            "example": "22K"
          },
          "estimate": {
            "type": "string",
            "nullable": true,
            "description": "Consensus forecast, as displayed",
            "example": "50K"
          },
          "actual": {
            "type": "string",
            "nullable": true,
            "description": "Released value, as displayed; null until the release",
            "example": null
          },
          "impact": {
            "type": "string",
            "enum": [
              "Low",
              "Medium",
              "High"
            ],
            "description": "Market impact"
          }
        }
      },
      "ScannerSignal": {
        "type": "object",
        "properties": {
          "direction": {
            "type": "string",
            "enum": [
              "LONG",
              "SHORT",
              "NEUTRAL"
            ]
          },
          "strength": {
            "type": "number",
            "example": 72
          },
          "confidence": {
            "type": "string",
            "enum": [
              "HIGH",
              "MEDIUM",
              "LOW"
            ]
          },
          "entry": {
            "type": "number"
          },
          "stopLoss": {
            "type": "number",
            "nullable": true
          },
          "takeProfit1": {
            "type": "number",
            "nullable": true
          },
          "takeProfit2": {
            "type": "number",
            "nullable": true
          },
          "takeProfit3": {
            "type": "number",
            "nullable": true
          },
          "riskRewardRatio": {
            "type": "number",
            "nullable": true
          },
          "reasoning": {
            "type": "string"
          }
        }
      },
      "LatencyProbeSummary": {
        "type": "object",
        "description": "Aggregate result for one probe type (TLS handshake or data endpoint) across every exchange in the run.",
        "properties": {
          "online": {
            "type": "integer",
            "example": 34
          },
          "offline": {
            "type": "integer",
            "example": 4
          },
          "timeout": {
            "type": "integer",
            "example": 2
          },
          "averageLatency": {
            "type": "number",
            "description": "Mean latency in ms (rounded) over probes with a positive latency; failed probes (-1) are excluded, and the value is 0 when none succeeded.",
            "example": 148
          }
        }
      },
      "ExchangeLatency": {
        "type": "object",
        "properties": {
          "exchange": {
            "type": "string",
            "description": "Stable lower-case venue key",
            "example": "binance"
          },
          "hostname": {
            "type": "string",
            "description": "Host of the venue's data endpoint, which is also the TLS probe target",
            "example": "fapi.binance.com"
          },
          "ip": {
            "type": "string",
            "nullable": true,
            "description": "IPv4 resolved for hostname, or null when DNS lookup failed",
            "example": "13.35.12.9"
          },
          "tlsLatency": {
            "type": "number",
            "description": "TLS-handshake time in ms, or -1 when the probe failed or timed out",
            "example": 42
          },
          "tlsStatus": {
            "type": "string",
            "enum": [
              "online",
              "offline",
              "timeout"
            ],
            "description": "\"online\" = handshake completed, \"timeout\" = socket timeout, \"offline\" = TCP/TLS error.",
            "example": "online"
          },
          "dataLatency": {
            "type": "number",
            "description": "Data-endpoint roundtrip in ms, or -1 when the probe failed or timed out",
            "example": 118
          },
          "dataStatus": {
            "type": "string",
            "enum": [
              "online",
              "offline",
              "timeout"
            ],
            "description": "\"online\" = HTTP 2xx or 400 (some APIs 400 a bare GET), \"timeout\" = aborted at the probe deadline, \"offline\" = network error or other non-2xx.",
            "example": "online"
          },
          "lastChecked": {
            "type": "integer",
            "format": "int64",
            "description": "Epoch ms at which both probes for this exchange finished",
            "example": 1785859200000
          },
          "tickerCount": {
            "type": "integer",
            "description": "Static per-venue market count from configuration, not measured",
            "example": 512
          },
          "org": {
            "type": "string",
            "description": "Hosting org from static lookup tables keyed by IP or hostname; \"Unknown\" when neither matches",
            "example": "Cloudflare"
          }
        }
      },
      "BreakoutSignal": {
        "type": "object",
        "description": "Volatility-squeeze breakout read for the same market",
        "properties": {
          "direction": {
            "type": "string"
          },
          "strength": {
            "type": "number"
          },
          "inSqueeze": {
            "type": "boolean"
          },
          "shiftBars": {
            "type": "integer"
          },
          "bandwidth": {
            "type": "number"
          },
          "squeezeBandwidth": {
            "type": "number"
          },
          "minBandwidth": {
            "type": "number"
          },
          "medianBandwidth": {
            "type": "number"
          },
          "upperAtShift": {
            "type": "number"
          },
          "lowerAtShift": {
            "type": "number"
          },
          "breakoutPct": {
            "type": "number",
            "nullable": true
          },
          "reasoning": {
            "type": "string"
          }
        }
      }
    },
    "securitySchemes": {
      "AuthToken": {
        "type": "apiKey",
        "in": "header",
        "name": "ttc-auth-token",
        "description": "Session token from Tetrac login (24-hour expiry)"
      },
      "PublicKey": {
        "type": "apiKey",
        "in": "header",
        "name": "ttc-public-key",
        "description": "Solana public key associated with the session token"
      },
      "X402Payment": {
        "type": "apiKey",
        "in": "header",
        "name": "x-x402-payment",
        "description": "Signed Solana USDC micropayment ($0.05 standard, $0.50 for the full-market scanner snapshot) \u2014 alternative to session auth"
      }
    }
  },
  "tags": [
    {
      "name": "Market Data",
      "description": "Perpetual tickers, funding rates, open interest, volume, listings and Solana perp positioning"
    },
    {
      "name": "Technical Analysis",
      "description": "Tetrac scanner multi-market technical analysis"
    },
    {
      "name": "Market Intelligence",
      "description": "News, the economic calendar, a momentum screener and the USGS significant-earthquake feed"
    },
    {
      "name": "Exchange Infrastructure",
      "description": "Exchange read operations and trade execution"
    }
  ],
  "security": [
    {
      "AuthToken": [],
      "PublicKey": []
    },
    {
      "X402Payment": []
    }
  ]
}
