openapi: 3.2.0 info: title: TradeDataHub Public Commerce API version: 1.0.0 description: Free machine-readable discovery endpoints over the canonical product catalog. servers: - url: https://www.tradedatahub.net tags: - name: Commerce description: x402 TESTNET paid retrieval. Mainnet is NOT enabled. paths: /api/v1/datasets/{product_id}/download: get: tags: - Commerce summary: Paid dataset retrieval via x402 (TESTNET ONLY) description: 'x402 paid retrieval. TESTNET ONLY: network is Base Sepolia (eip155:84532); mainnet settlement is NOT enabled. With no PAYMENT-SIGNATURE header the endpoint returns HTTP 402 Payment Required including the current x402 Payment-Required challenge (the server generates it dynamically; do not hardcode it). After a valid TESTNET settlement the endpoint returns 200 with a one-shot authorized download URL. Human Stripe purchasing is a separate, unchanged path. Agents may inspect the 402 challenge without making any payment.' parameters: - $ref: '#/components/parameters/ProductId' responses: '200': description: Authorized delivery after valid TESTNET settlement (one-shot download URL) content: application/json: schema: type: object required: - api_version - product_id - download_url properties: api_version: type: string product_id: type: string filename: type: string download_url: type: string record_count: type: integer '402': description: Payment Required — includes the current x402 Payment-Required challenge content: application/json: schema: $ref: '#/components/schemas/PaymentRequired' '400': description: Invalid payment payload/signature (fail-closed) content: application/json: schema: $ref: '#/components/schemas/Error' '404': description: Dataset not found, or the testnet rail is disabled (fail-closed `not_yet_available`) content: application/json: schema: $ref: '#/components/schemas/Error' '409': description: Payment replay / duplicate settlement rejected (fail-closed) content: application/json: schema: $ref: '#/components/schemas/Error' operationId: getApiV1DatasetsByProductIdDownload 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 PaymentRequired: type: object required: - api_version - error - payment_required description: HTTP 402 body. The live challenge is generated dynamically by the server; treat the `payment_required` object as authoritative and never hardcode it. TESTNET ONLY (Base Sepolia eip155:84532). properties: api_version: type: string error: type: object properties: code: type: string example: payment_required message: type: string payment_required: type: object properties: x402Version: type: integer resource: type: object properties: url: type: string mimeType: type: string accepts: type: array items: type: object required: - network - asset - amount - payTo properties: network: type: string description: CAIP-2 chain id; testnet is `eip155:84532` (Base Sepolia). asset: type: string description: USDC contract address on the testnet network. amount: type: string description: Atomic units (6 decimals). payTo: type: string description: Testnet recipient address. parameters: ProductId: name: product_id in: path required: true schema: type: string maxLength: 128 description: 'Canonical product identifier. Formats: `state:{state_slug}` (e.g. `state:texas`), `state-trade:{state_slug}:{trade_slug}` (e.g. `state-trade:florida:roofer`), `city-trade:{state_slug}:{city_slug}:{trade_slug}` (e.g. `city-trade:texas:austin:plumber`), `mega-pack:seven-live-states`. Slugs are lowercase hyphenated; always derive product_id values from the discovery endpoints rather than constructing them ad hoc.'