openapi: 3.2.0 info: title: TradeDataHub Public Discovery API version: 1.0.0 description: Free machine-readable discovery endpoints over the canonical product catalog. servers: - url: https://www.tradedatahub.net tags: - name: Discovery description: Zero-knowledge inventory discovery (coverage, states, trades, cities). paths: /api/v1/: get: tags: - Discovery summary: API index — endpoint list and paid access pointer description: Returns the free discovery endpoint list and the x402 TESTNET paid endpoint pointer. responses: '200': description: Endpoint index content: application/json: schema: type: object required: - api_version - endpoints properties: api_version: type: string endpoints: type: array items: type: string paid_endpoint: type: string description: x402 TESTNET ONLY (Base Sepolia eip155:84532); unpaid requests receive HTTP 402 Payment Required with the challenge; mainnet settlement is NOT enabled. operationId: getApiV1 x-operation-id-source: derived /api/v1/texas-trades-teaser.json: get: tags: - Discovery summary: Get a browser-safe masked trade-business teaser responses: '200': description: Masked teaser without paid contact records content: application/json: schema: $ref: '#/components/schemas/Preview' operationId: getApiV1TexasTradesTeaserJson x-operation-id-source: derived /api/v1/coverage: get: tags: - Discovery summary: Overall platform coverage and pricing model (start here) responses: '200': description: Coverage summary content: application/json: schema: $ref: '#/components/schemas/Coverage' example: api_version: 1.0.0 record_count: 33753 live_states: 7 trades: 50 cities: 170 product_count: 8588 currency: usd price_model: one-time CSV per dataset last_updated: '2026-08-19' operationId: getApiV1Coverage x-operation-id-source: derived /api/v1/states: get: tags: - Discovery summary: List live states with record counts and prices responses: '200': description: States content: application/json: schema: type: object required: - api_version - states properties: api_version: type: string states: type: array items: $ref: '#/components/schemas/State' operationId: getApiV1States x-operation-id-source: derived /api/v1/trades: get: tags: - Discovery summary: List trades with aggregate record counts responses: '200': description: Trades content: application/json: schema: type: object required: - api_version - trades properties: api_version: type: string trades: type: array items: $ref: '#/components/schemas/Trade' operationId: getApiV1Trades x-operation-id-source: derived /api/v1/cities: get: tags: - Discovery summary: List cities (filter by ?state=) parameters: - name: state in: query required: false schema: type: string description: Exact state name as returned by /api/v1/states, e.g. `Texas` (case-sensitive). responses: '200': description: Cities (paginated) content: application/json: schema: type: object required: - api_version - pagination - cities properties: api_version: type: string pagination: $ref: '#/components/schemas/Pagination' cities: type: array items: $ref: '#/components/schemas/City' '404': description: Unknown state content: application/json: schema: $ref: '#/components/schemas/Error' operationId: getApiV1Cities x-operation-id-source: derived components: schemas: Error: type: object required: - api_version - error properties: api_version: type: string error: type: object required: - code - message properties: code: type: string message: type: string details: type: object additionalProperties: true Trade: type: object required: - trade - record_count - product_count properties: trade: type: string record_count: type: integer product_count: type: integer State: type: object required: - product_id - state - record_count - price - currency properties: product_id: type: string state: type: string record_count: type: integer amount_cents: type: integer price: type: string currency: type: string last_updated: type: string available_for_purchase: type: boolean PreviewRecord: type: object required: - business - city - trade - phone_available - website_available properties: business: type: string description: Always the literal `Masked business` in previews. example: Masked business city: type: string trade: type: string phone_available: type: boolean description: Whether the purchased record includes a phone value. website_available: type: boolean description: Whether the purchased record includes a website value. verification_date: type: string description: Source-pipeline verification date (YYYY-MM-DD). Coverage: type: object required: - api_version - record_count - currency - price_model properties: api_version: type: string record_count: type: integer live_states: type: integer trades: type: integer cities: type: integer product_count: type: integer currency: type: string price_model: type: string last_updated: type: string nullable: true City: type: object required: - state - city - record_count - trade_count properties: state: type: string city: type: string record_count: type: integer trade_count: type: integer Preview: type: object required: - api_version - product_id - classification - records properties: api_version: type: string product_id: type: string classification: type: string record_count: type: integer fields: type: array items: type: string records: type: array items: $ref: '#/components/schemas/PreviewRecord' notice: type: string Pagination: type: object required: - total - limit - offset properties: total: type: integer limit: type: integer offset: type: integer