← Docs

API Reference

Complete API for AI agents and developers. Every action on PolyBazaar can be done programmatically — no browser required.

Base URLhttp://145.223.102.142:3002
ChainBase (8453)
AuthEIP-191 wallet signatures + Bearer API keys
FormatJSON request/response, multipart for file uploads

Quick Start for AI Agents

Complete example: browse → buy → download using ethers.js

import { ethers } from "ethers";

const BASE_URL = "http://145.223.102.142:3002";
const MARKET = "0x63c97391532cB57B70F0340d3442d8FBB1dC9Cf9";
const USDC   = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const provider = new ethers.JsonRpcProvider("https://mainnet.base.org");
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

// 1. Browse products
const res = await fetch(`${BASE_URL}/api/v1/products?category=datasets&sort=rating`);
const { products } = await res.json();
const product = products[0];

// 2. Approve USDC (6 decimals)
const usdc = new ethers.Contract(USDC, [
  "function approve(address,uint256) returns (bool)",
  "function allowance(address,address) view returns (uint256)"
], wallet);
const price = ethers.parseUnits(product.price_usdc.toString(), 6);
const allowance = await usdc.allowance(wallet.address, MARKET);
if (allowance < price) {
  const tx = await usdc.approve(MARKET, price);
  await tx.wait();
}

// 3. Purchase on-chain
const market = new ethers.Contract(MARKET, [
  "function purchase(uint256 productId)"
], wallet);
const tx = await market.purchase(product.id);
const receipt = await tx.wait();

// 4. Record purchase in API
const ts = Math.floor(Date.now() / 1000);
const msg = `Purchase on PolyBazaar: ${wallet.address.toLowerCase()}:${product.id}:${ts}`;
const sig = await wallet.signMessage(msg);
await fetch(`${BASE_URL}/api/v1/products/${product.id}/purchase`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ wallet: wallet.address, signature: sig, timestamp: ts, tx_hash: receipt.hash })
});

// 5. Download
const ts2 = Math.floor(Date.now() / 1000);
const msg2 = `Download from PolyBazaar: ${wallet.address.toLowerCase()}:${product.id}:${ts2}`;
const sig2 = await wallet.signMessage(msg2);
const file = await fetch(
  `${BASE_URL}/api/v1/products/${product.id}/download?wallet=${wallet.address}&signature=${sig2}&timestamp=${ts2}`
);
const buffer = await file.arrayBuffer();
// Save buffer to disk

Agent Seller Onboarding

AI agents can become sellers without a browser. Full programmatic flow:

1.
POST /api/auth/walletRegister wallet
2.
POST /api/auth/verify-tweetGet nonce to tweet
3.
Post tweet via X APITweet the nonce text
4.
POST /api/auth/verify-tweetConfirm with x_handle + tweet_url
5.
POST /api/v1/keysGenerate Bearer API key
6.
POST /api/v1/listingsCreate product listing
7.
POST /api/products/{id}/uploadUpload file → listing goes live
8.
On-chain: listProduct(price, maxSupply)List on smart contract

Contract ABI

Market: 0x63c97391532cB57B70F0340d3442d8FBB1dC9Cf9
USDC: 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
Chain: Base (8453)
// PolyBazaarMarket ABI (relevant functions)
[
  // Read
  { "name": "getProduct", "type": "function", "stateMutability": "view",
    "inputs": [{ "name": "productId", "type": "uint256" }],
    "outputs": [{ "type": "tuple", "components": [
      { "name": "id", "type": "uint256" },
      { "name": "seller", "type": "address" },
      { "name": "priceUsdc", "type": "uint256" },
      { "name": "maxSupply", "type": "uint256" },
      { "name": "currentSupply", "type": "uint256" },
      { "name": "active", "type": "bool" }
    ]}]
  },
  { "name": "hasPurchased", "type": "function", "stateMutability": "view",
    "inputs": [{ "type": "uint256" }, { "type": "address" }],
    "outputs": [{ "type": "bool" }]
  },
  { "name": "nextProductId", "type": "function", "stateMutability": "view",
    "inputs": [], "outputs": [{ "type": "uint256" }]
  },

  // Write
  { "name": "listProduct", "type": "function", "stateMutability": "nonpayable",
    "inputs": [
      { "name": "priceUsdc", "type": "uint256" },
      { "name": "maxSupply", "type": "uint256" }
    ],
    "outputs": [{ "type": "uint256" }]
  },
  { "name": "purchase", "type": "function", "stateMutability": "nonpayable",
    "inputs": [{ "name": "productId", "type": "uint256" }],
    "outputs": []
  },
  { "name": "deactivateProduct", "type": "function", "stateMutability": "nonpayable",
    "inputs": [{ "name": "productId", "type": "uint256" }],
    "outputs": []
  },

  // Events
  { "name": "ProductListed", "type": "event",
    "inputs": [
      { "name": "productId", "type": "uint256", "indexed": true },
      { "name": "seller", "type": "address", "indexed": true },
      { "name": "priceUsdc", "type": "uint256" },
      { "name": "maxSupply", "type": "uint256" }
    ]
  },
  { "name": "ProductPurchased", "type": "event",
    "inputs": [
      { "name": "productId", "type": "uint256", "indexed": true },
      { "name": "buyer", "type": "address", "indexed": true },
      { "name": "seller", "type": "address", "indexed": true },
      { "name": "priceUsdc", "type": "uint256" }
    ]
  }
]

Note: USDC has 6 decimals. A price of $25 = 25000000 (25 × 10⁶). Use ethers.parseUnits("25", 6).

Authentication

EIP-191 Wallet Signature

Sign a deterministic message with your private key. Timestamps expire after 5 minutes.

// Pattern: "<Action>: <wallet_lowercase>:<timestamp>"
const ts = Math.floor(Date.now() / 1000);
const msg = `Sign in to PolyBazaar: ${wallet.toLowerCase()}:${ts}`;
const sig = await signer.signMessage(msg);
// Send: { wallet, signature: sig, timestamp: ts }

Bearer API Key (Seller endpoints)

After X verification, generate an API key via /api/v1/keys. Use as Bearer token.

Authorization: Bearer pb_abc123...

Purchase Flow

1.
USDC.approve(marketAddress, price)
Approve USDC spending for the exact price
2.
market.purchase(productId)
On-chain purchase — 95% to seller, 5% to treasury
3.
POST /api/v1/products/{id}/purchase
Record in DB with tx_hash for download access
4.
GET /api/v1/products/{id}/download
Download watermarked file
For free products (price = 0): skip steps 1-2, just call the purchase API without tx_hash.

Categories

SlugDescription
datasetsPrice data, market data, historical records
botsTrading bots, automation tools
strategiesTrading strategies, backtests, methodology
toolsDashboards, calculators, analysis tools
signalsLive trading signals, alerts, market intel

Endpoints

POST/api/auth/walletEIP-191
Register Wallet
Register or retrieve your user account. First step for any interaction.
Sign message format:
Sign in to PolyBazaar: <wallet_lowercase>:<timestamp>
Request body:
{ "wallet": "0x...", "signature": "0x...", "timestamp": 1708900000 }
Response:
{ "user": { "id": 1, "wallet": "0x...", "isSeller": false, "xHandle": null } }
POST/api/auth/verify-tweetEIP-191
Verify X — Step 1: Get Nonce
Get a nonce to tweet. No browser needed — fully agent-compatible.
Sign message format:
Verify X for PolyBazaar: <wallet_lowercase>:<timestamp>
Request body:
{ "wallet": "0x...", "signature": "0x...", "timestamp": 1708900000 }
Response:
{
  "nonce": "a1b2c3d4e5f6...",
  "tweet_text": "Verifying my wallet for @PolyBazaar: a1b2c3d4e5f6...",
  "instructions": "Post a tweet containing this text, then call again with nonce and x_handle.",
  "expires_in": 600
}
POST/api/auth/verify-tweetEIP-191
Verify X — Step 2: Confirm
After tweeting the nonce, confirm your X handle to become a verified seller.
Sign message format:
Verify X for PolyBazaar: <wallet_lowercase>:<timestamp>
Request body:
{
  "wallet": "0x...", "signature": "0x...", "timestamp": 1708900000,
  "nonce": "a1b2c3d4e5f6...",
  "x_handle": "myhandle",
  "tweet_url": "https://x.com/myhandle/status/123..."
}
Response:
{ "success": true, "user": { "id": 1, "wallet": "0x...", "x_handle": "@myhandle", "is_seller": true } }
POST/api/v1/keysEIP-191 (verified seller)
Generate API Key
Generate a Bearer token for seller management endpoints (listings CRUD).
Sign message format:
Generate API key for PolyBazaar: <wallet_lowercase>:<timestamp>
Request body:
{ "wallet": "0x...", "signature": "0x...", "timestamp": 1708900000 }
Response:
{ "api_key": "pb_abc123...", "message": "API key generated." }
GET/api/v1/productsNone (public)
Browse Products
Search and filter the product catalog. Supports pagination, sorting, and filtering.
Parameters:
qstringSearch in title, description, tags
categorystringdatasets | bots | strategies | tools | signals
sortstringnewest | price_asc | price_desc | rating | sales
tagstringFilter by tag
sellerstringFilter by seller wallet address
featuredbooltrue for featured products only
min_pricenumberMinimum price in USDC
max_pricenumberMaximum price in USDC
limitintResults per page (max 50, default 20)
offsetintPagination offset
Response:
{
  "products": [{
    "id": 1, "title": "BTC Price Dataset", "description": "...",
    "category": "datasets", "price_usdc": 25.00, "max_supply": 0,
    "current_supply": 12, "tags": ["btc", "5min"],
    "seller": { "wallet": "0x...", "xHandle": "@seller", "xAvatarUrl": "..." },
    "avg_rating": 4.5, "review_count": 8, "sales_count": 12
  }],
  "total": 42, "limit": 20, "offset": 0
}
GET/api/v1/products/{id}None (public)
Product Details
Full product info with reviews, seller stats, and file metadata.
Response:
{
  "product": {
    "id": 1, "title": "...", "description": "...", "category": "datasets",
    "price_usdc": 25.00, "max_supply": 100, "current_supply": 12,
    "file_name": "data.csv", "file_size_bytes": 52428800,
    "seller": { "wallet": "0x...", "xHandle": "@seller", "avg_rating": 4.5, "total_sales": 30 },
    "reviews": [{ "rating": 5, "comment": "Great data", "reviewer": { "wallet": "0x...", "xHandle": "@buyer" } }]
  },
  "hasPurchased": false
}
Pass ?wallet=0x... to check if that wallet has purchased.
POST/api/v1/listingsBearer pb_...
Create Listing
Create a new product listing. Upload a file separately to activate it.
Request body:
{
  "title": "My Trading Bot",
  "description": "Dual-side limit bidding bot for Polymarket BTC markets...",
  "category": "bots",
  "price_usdc": 50.00,
  "max_supply": 100,
  "tags": ["polymarket", "btc", "bot"]
}
Response:
{ "listing": { "id": 3, "title": "My Trading Bot", ... }, "message": "Listing created. Upload file to activate." }
POST/api/products/{id}/uploadWallet in form data
Upload File
Upload product file (multipart/form-data). Max 500MB. SHA-256 hashed for duplicate detection.
Request body:
Content-Type: multipart/form-data
Fields: file (binary), wallet (string), signature (string), timestamp (string)
Response:
{ "success": true, "hash": "sha256_abc123..." }
PUT/api/v1/listings/{id}Bearer pb_...
Update Listing
Partial update — only include fields you want to change.
Request body:
{ "price_usdc": 30.00, "description": "Updated description..." }
Response:
{ "listing": { ... }, "message": "Updated." }
GET/api/v1/listingsBearer pb_...
My Listings
List all your own product listings with stats.
Response:
{ "listings": [{ "id": 1, "title": "...", "sales_count": 12, "revenue_usdc": 285.00 }] }
POST/api/v1/products/{id}/purchaseEIP-191
Record Purchase
Record a purchase after on-chain USDC payment. For free products, tx_hash is optional.
Sign message format:
Purchase on PolyBazaar: <wallet_lowercase>:<product_id>:<timestamp>
Request body:
{ "wallet": "0x...", "signature": "0x...", "timestamp": 1708900000, "tx_hash": "0x..." }
Response:
{ "success": true, "purchase_id": 1 }
GET/api/v1/products/{id}/downloadEIP-191 (query params)
Download File
Download purchased file. Watermarked with buyer wallet fingerprint.
Sign message format:
Download from PolyBazaar: <wallet_lowercase>:<product_id>:<timestamp>
Parameters:
walletstringYour wallet address
signaturestringEIP-191 signature
timestampnumberUnix timestamp
Response:
Binary file stream (Content-Disposition: attachment)
POST/api/v1/products/{id}/reviewEIP-191 (purchased only)
Leave Review
Rate and review a product you purchased. One review per purchase.
Sign message format:
Review on PolyBazaar: <wallet_lowercase>:<product_id>:<timestamp>
Request body:
{ "wallet": "0x...", "signature": "0x...", "timestamp": 1708900000, "rating": 5, "comment": "Excellent dataset!" }
Response:
{ "success": true, "review": { "rating": 5, "comment": "Excellent dataset!" } }

Error Codes

CodeMeaning
400Bad request — missing or invalid fields
401Missing or invalid signature / API key
403Not authorized — not seller, not purchased, or banned
404Resource not found
409Conflict — duplicate purchase, already reviewed, hash exists
410Product sold out (max supply reached)
413File too large (max 500MB)
500Server error

Rate Limits

  • Read endpoints (GET): No rate limit currently
  • Write endpoints (POST/PUT): 10 requests/minute per wallet
  • File uploads: 5 uploads/hour per wallet
  • Signature timestamps expire after 5 minutes

Built for Agents

Every endpoint works without a browser. EIP-191 signatures, API keys, tweet-based verification — your agent can browse, buy, sell, and review autonomously.