Skip to main content

Marketplace API - AI Conversational Commerce

The Marketplace API provides AI-powered conversational commerce functionality enabling users to discover, search, and purchase products from multiple marketplaces (Etsy, Tokopedia) using natural language and pay with USDC cryptocurrency. Built for seamless cross-border shopping with blockchain payment integration.

🎯 What Can You Manage?

Your complete conversational commerce ecosystem with these powerful tools:

  • AI Chat Assistant: Natural language product discovery powered by Groq AI (Llama 3.1 70B)
  • Multi-Marketplace Search: Simultaneous product search across Etsy (USD) and Tokopedia (IDR)
  • Product Normalization: Unified product schema across different marketplaces
  • Order Management: Create and track orders with USDC payment integration
  • Payment Tracking: Real-time blockchain payment monitoring via smart contract events
  • Currency Conversion: Automatic FX conversion for IDR products to USDC
  • Order History: Complete order tracking with pagination and status filtering

🧩 Your Marketplace Building Blocks

💬 Chat Operations Blocks

  • POST /api/marketplace/chat - Send message to AI shopping assistant (No Auth)

🔍 Search Operations Blocks

  • POST /api/marketplace/search - Search products across marketplaces (No Auth)

📦 Order Operations Blocks

  • POST /api/marketplace/orders - Create new order (Auth Required)
  • GET /api/marketplace/orders/:order_id - Get order details (Auth Required)
  • GET /api/marketplace/orders - Get user order history (Auth Required)

🏗️ Common Usage Patterns

Pattern 1: "I want to find products using natural language"

Chat with AI → Get product recommendations → Search products

Use: /marketplace/chat/marketplace/search

Pattern 2: "I want to buy a product with USDC"

Search product → Create order → Pay with USDC → Track status

Use: /marketplace/search/marketplace/orders (POST) → /marketplace/orders/:order_id (GET)

Pattern 3: "I want to see my purchase history"

Get order history → Filter by status → Check payment status

Use: /marketplace/orders (GET) with pagination

Pattern 4: "I want to shop across multiple countries"

Search Etsy (USD) + Tokopedia (IDR) → Compare prices → Order with auto FX conversion

Use: /marketplace/search with sources: ['etsy', 'tokopedia']


🔐 Authentication

Marketplace API has mixed authentication requirements:

No Authentication Required

  • Chat: /api/marketplace/chat - Public access for AI assistant
  • Search: /api/marketplace/search - Public access for product search

Authentication Required

  • Create Order: /api/marketplace/orders (POST)
  • Get Order: /api/marketplace/orders/:order_id (GET)
  • Order History: /api/marketplace/orders (GET)

Required Headers (Auth endpoints only)

Authorization: Bearer YOUR_JWT_TOKEN
x-api-key: YOUR_API_KEY
Content-Type: application/json

Getting JWT Token

curl -X POST https://api.brdz.link/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"usernameoremail": "user@example.com",
"password": "your_password"
}'

Response:

{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user_id": 123,
"role": "user"
}

💬 Chat Operations

Send Message to AI Assistant

POST/api/marketplace/chat

Send Message to AI Shopping Assistant

Interact with AI-powered shopping assistant using natural language. The assistant helps users discover products, provides recommendations, and guides through the purchase process. Powered by Groq AI (Llama 3.1 70B) with intent detection (SEARCH, BUY, INFO, HELP). No authentication required - public access.

Parameters

messagestringrequired

User's message to the AI assistant

conversation_historyarray

Previous conversation messages for context (default: [])

Request Body

{
  "message": "I'm looking for handmade ceramic mugs under $30",
  "conversation_history": [
    {
      "role": "user",
      "content": "Hi, I need a gift"
    },
    {
      "role": "assistant",
      "content": "I'd be happy to help you find a gift! What kind of gift are you looking for?"
    }
  ]
}

Response

200AI response generated successfully
{
  "success": true,
  "reply": "Great! I can help you find handmade ceramic mugs. Here are some beautiful options:\n\n1. Artisan Blue Ceramic Mug - $24.99 (Etsy)\n2. Handcrafted Pottery Mug Set - $28.50 (Etsy)\n3. Rustic Stoneware Mug - $22.00 (Tokopedia - IDR 349,000)\n\nWould you like me to search for more options or provide details about any of these?",
  "intent": "SEARCH",
  "usage": {
    "prompt_tokens": 245,
    "completion_tokens": 128,
    "total_tokens": 373
  }
}
400Invalid request - message required
{
  "success": false,
  "error": "Message required"
}
500Chat service unavailable
{
  "success": false,
  "error": "Chat service unavailable",
  "details": "Groq API error"
}
curl -X POST https://api.brdz.link/api/marketplace/chat \
-H "Content-Type: application/json" \
-d '{
  "message": "I'''m looking for handmade ceramic mugs under $30",
  "conversation_history": []
}'

🔍 Search Operations

Search Products Across Marketplaces

POST/api/marketplace/search

Search Products Across Multiple Marketplaces

Search for products across Etsy (USD) and Tokopedia (IDR) marketplaces. Uses AI-powered query generation to optimize search results. Products are normalized into unified schema with automatic currency conversion for IDR items. Returns sorted results with price, images, vendor info, and direct purchase links. No authentication required - public access.

Parameters

querystringrequired

Search query (e.g., 'handmade ceramic mug')

sourcesarray

Marketplaces to search: ['etsy', 'tokopedia'] (default: ['etsy'])

limitnumber

Maximum products to return (default: 10, max: 50)

Request Body

{
  "query": "handmade ceramic travel mug",
  "sources": [
    "etsy",
    "tokopedia"
  ],
  "limit": 10
}

Response

200Products retrieved successfully
{
  "success": true,
  "query": "handmade ceramic travel mug",
  "products": [
    {
      "productId": "etsy-123456",
      "title": "Handmade Ceramic Travel Mug with Lid",
      "description": "Beautiful handcrafted ceramic travel mug...",
      "image": "https://i.etsystatic.com/...",
      "images": [
        "https://i.etsystatic.com/..."
      ],
      "source": "etsy",
      "url": "https://www.etsy.com/listing/123456",
      "vendor": {
        "name": "Etsy - PotteryShop",
        "marketplace": "etsy",
        "shop_name": "PotteryShop",
        "shop_url": "https://www.etsy.com/shop/PotteryShop"
      },
      "pricing": {
        "price": 28.5,
        "currency": "USD",
        "original_price": 28.5,
        "shipping": 5,
        "total": 33.5
      },
      "availability": "in_stock",
      "metadata": {
        "rating": 4.8,
        "num_favorers": 1250,
        "tags": [
          "ceramic",
          "handmade",
          "travel mug"
        ]
      }
    },
    {
      "productId": "tokopedia-789012",
      "title": "Gelas Keramik Travel Handmade Premium",
      "description": "Gelas keramik travel buatan tangan...",
      "image": "https://images.tokopedia.net/...",
      "images": [
        "https://images.tokopedia.net/..."
      ],
      "source": "tokopedia",
      "url": "https://www.tokopedia.com/...",
      "vendor": {
        "name": "Tokopedia - KeramikArt",
        "marketplace": "tokopedia",
        "shop_name": "KeramikArt",
        "shop_url": "https://www.tokopedia.com/keramikart",
        "shop_location": "Jakarta Selatan"
      },
      "pricing": {
        "price": 22.15,
        "currency": "USD",
        "original_price": 350000,
        "original_currency": "IDR",
        "shipping": 0,
        "total": 22.15,
        "fx_rate": 15850
      },
      "availability": "in_stock",
      "metadata": {
        "rating": 4.9,
        "total_sold": 342,
        "stock": 45,
        "condition": "new"
      }
    }
  ],
  "count": 10,
  "search_queries": [
    "handmade ceramic travel mug",
    "pottery travel cup",
    "gelas keramik travel"
  ]
}
400Invalid request - query required
{
  "success": false,
  "error": "Search query required"
}
500Search failed
{
  "success": false,
  "error": "Search failed",
  "details": "Scraper timeout"
}
curl -X POST https://api.brdz.link/api/marketplace/search \
-H "Content-Type: application/json" \
-d '{
  "query": "handmade ceramic travel mug",
  "sources": ["etsy", "tokopedia"],
  "limit": 10
}'

📦 Order Operations

Create Order

POST/api/marketplace/orders

Create Marketplace Order

Create a new marketplace order for selected product. Calculates USDC payment amount with automatic FX conversion for IDR products. Saves order to database with PENDING status. Returns payment details for blockchain transaction. Requires authentication.

Parameters

productobjectrequired

Product details from search results

recipientobjectrequired

Delivery recipient information

wallet_addressstringrequired

User's wallet address for payment tracking

chain_idstring

Blockchain network (default: 'sepolia')

Request Body

{
  "product": {
    "productId": "etsy-123456",
    "title": "Handmade Ceramic Travel Mug",
    "description": "Beautiful handcrafted ceramic travel mug with lid",
    "image": "https://i.etsystatic.com/...",
    "url": "https://www.etsy.com/listing/123456",
    "source": "etsy",
    "vendor": {
      "name": "Etsy - PotteryShop",
      "marketplace": "etsy",
      "shop_name": "PotteryShop",
      "shop_url": "https://www.etsy.com/shop/PotteryShop"
    },
    "pricing": {
      "price": 28.5,
      "currency": "USD",
      "total": 33.5,
      "shipping": 5
    }
  },
  "recipient": {
    "name": "John Doe",
    "phone": "+628123456789",
    "address": "Jl. Sudirman No. 123, Jakarta Selatan 12190, Indonesia",
    "email": "john@example.com",
    "notes": "Please call before delivery"
  },
  "wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "chain_id": "sepolia"
}

Response

201Order created successfully
{
  "success": true,
  "order": {
    "order_id": "BRDZ-1705308000000-a1b2c3d4",
    "user_id": 456,
    "product_data": {
      "id": "etsy-123456",
      "title": "Handmade Ceramic Travel Mug",
      "description": "Beautiful handcrafted ceramic travel mug...",
      "image": "https://i.etsystatic.com/...",
      "url": "https://www.etsy.com/listing/123456",
      "source": "etsy"
    },
    "vendor_data": {
      "name": "Etsy - PotteryShop",
      "marketplace": "etsy",
      "shop_name": "PotteryShop",
      "shop_url": "https://www.etsy.com/shop/PotteryShop"
    },
    "pricing_data": {
      "original_price": 28.5,
      "original_currency": "USD",
      "usd_amount": 33.5,
      "usdc_amount": 33.5,
      "shipping": 5,
      "total_usd": 33.5,
      "fx_rate": null,
      "fx_timestamp": "2024-01-15T10:00:00Z"
    },
    "recipient_data": {
      "name": "John Doe",
      "phone": "+628123456789",
      "address": "Jl. Sudirman No. 123, Jakarta Selatan 12190",
      "email": "john@example.com",
      "notes": "Please call before delivery"
    },
    "payment_token": "USDC",
    "token_amount": 33.5,
    "fiat_amount": 28.5,
    "fiat_currency": "USD",
    "chain_id": "sepolia",
    "wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
    "contract_address": "0x7E93334bf4Cd3Bd15D2203D7E6d5A59A891C4a48",
    "payment_status": "PENDING",
    "created_at": "2024-01-15T10:00:00Z"
  },
  "payment_details": {
    "order_id": "BRDZ-1705308000000-a1b2c3d4",
    "usdc_amount": 33.5,
    "contract_address": "0x7E93334bf4Cd3Bd15D2203D7E6d5A59A891C4a48",
    "chain_id": "sepolia",
    "wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb"
  }
}
400Invalid request - missing required fields
{
  "success": false,
  "error": "Missing required fields: product, recipient, wallet_address"
}
401Authentication required
{
  "success": false,
  "error": "Authentication required"
}
500Failed to create order
{
  "success": false,
  "error": "Failed to create order",
  "details": "Database error"
}
curl -X POST https://api.brdz.link/api/marketplace/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
  "product": {
    "productId": "etsy-123456",
    "title": "Handmade Ceramic Travel Mug",
    "description": "Beautiful handcrafted ceramic travel mug with lid",
    "image": "https://i.etsystatic.com/...",
    "url": "https://www.etsy.com/listing/123456",
    "source": "etsy",
    "vendor": {
      "name": "Etsy - PotteryShop",
      "marketplace": "etsy",
      "shop_name": "PotteryShop",
      "shop_url": "https://www.etsy.com/shop/PotteryShop"
    },
    "pricing": {
      "price": 28.50,
      "currency": "USD",
      "total": 33.50,
      "shipping": 5.00
    }
  },
  "recipient": {
    "name": "John Doe",
    "phone": "+628123456789",
    "address": "Jl. Sudirman No. 123, Jakarta Selatan 12190, Indonesia",
    "email": "john@example.com",
    "notes": "Please call before delivery"
  },
  "wallet_address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
  "chain_id": "sepolia"
}'

Get Order Details

GET/api/marketplace/orders/:order_id

Get Order Details by ID

Retrieve complete order details including product info, pricing, recipient data, payment status, and blockchain transaction hash. Users can only access their own orders, admins can access any order. Requires authentication.

Parameters

order_idstringrequired

Order ID (format: BRDZ-{timestamp}-{uuid})

Response

200Order retrieved successfully
{
  "success": true,
  "order": {
    "order_id": "BRDZ-1705308000000-a1b2c3d4",
    "user_id": 456,
    "product_data": {
      "id": "etsy-123456",
      "title": "Handmade Ceramic Travel Mug",
      "description": "Beautiful handcrafted ceramic travel mug...",
      "image": "https://i.etsystatic.com/...",
      "url": "https://www.etsy.com/listing/123456",
      "source": "etsy"
    },
    "vendor_data": {
      "name": "Etsy - PotteryShop",
      "marketplace": "etsy",
      "shop_name": "PotteryShop",
      "shop_url": "https://www.etsy.com/shop/PotteryShop"
    },
    "pricing_data": {
      "original_price": 28.5,
      "original_currency": "USD",
      "usd_amount": 33.5,
      "usdc_amount": 33.5,
      "total_usd": 33.5
    },
    "recipient_data": {
      "name": "John Doe",
      "phone": "+628123456789",
      "address": "Jl. Sudirman No. 123, Jakarta Selatan 12190",
      "email": "john@example.com"
    },
    "payment_token": "USDC",
    "token_amount": 33.5,
    "payment_status": "PAID",
    "blockchain_tx_hash": "0xabc123...",
    "created_at": "2024-01-15T10:00:00Z",
    "paid_at": "2024-01-15T10:05:00Z",
    "completed_at": null
  }
}
401Authentication required
{
  "success": false,
  "error": "Authentication required"
}
403Access denied - not your order
{
  "success": false,
  "error": "Access denied"
}
404Order not found
{
  "success": false,
  "error": "Order not found"
}
500Failed to get order
{
  "success": false,
  "error": "Failed to get order",
  "details": "Database error"
}
curl -X GET https://api.brdz.link/api/marketplace/orders/BRDZ-1705308000000-a1b2c3d4 \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "x-api-key: YOUR_API_KEY"

Get User Order History

GET/api/marketplace/orders

Get User Order History

Retrieve paginated order history for authenticated user. Supports filtering by payment status and pagination. Returns orders sorted by creation date (newest first). Requires authentication.

Parameters

limitnumber

Maximum orders to return (default: 10, max: 100)

offsetnumber

Number of orders to skip (default: 0)

statusstring

Filter by status: PENDING, PAID, COMPLETED, FAILED, CANCELLED

Response

200Orders retrieved successfully
{
  "success": true,
  "orders": [
    {
      "order_id": "BRDZ-1705308000000-a1b2c3d4",
      "user_id": 456,
      "product_data": {
        "id": "etsy-123456",
        "title": "Handmade Ceramic Travel Mug",
        "image": "https://i.etsystatic.com/...",
        "source": "etsy"
      },
      "vendor_data": {
        "name": "Etsy - PotteryShop",
        "marketplace": "etsy"
      },
      "pricing_data": {
        "usdc_amount": 33.5,
        "original_currency": "USD"
      },
      "payment_status": "PAID",
      "blockchain_tx_hash": "0xabc123...",
      "created_at": "2024-01-15T10:00:00Z",
      "paid_at": "2024-01-15T10:05:00Z"
    },
    {
      "order_id": "BRDZ-1705221600000-e5f6g7h8",
      "user_id": 456,
      "product_data": {
        "id": "tokopedia-789012",
        "title": "Gelas Keramik Premium",
        "image": "https://images.tokopedia.net/...",
        "source": "tokopedia"
      },
      "vendor_data": {
        "name": "Tokopedia - KeramikArt",
        "marketplace": "tokopedia"
      },
      "pricing_data": {
        "usdc_amount": 22.15,
        "original_currency": "IDR",
        "original_price": 350000
      },
      "payment_status": "COMPLETED",
      "blockchain_tx_hash": "0xdef456...",
      "created_at": "2024-01-14T09:00:00Z",
      "paid_at": "2024-01-14T09:03:00Z",
      "completed_at": "2024-01-18T14:30:00Z"
    }
  ],
  "pagination": {
    "total": 15,
    "limit": 10,
    "offset": 0,
    "has_more": true
  }
}
401Authentication required
{
  "success": false,
  "error": "Authentication required"
}
500Failed to get orders
{
  "success": false,
  "error": "Failed to get orders",
  "details": "Database error"
}
# Get recent orders
curl -X GET "https://api.brdz.link/api/marketplace/orders?limit=10&offset=0" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "x-api-key: YOUR_API_KEY"

# Filter by status
curl -X GET "https://api.brdz.link/api/marketplace/orders?status=PAID&limit=20" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "x-api-key: YOUR_API_KEY"

🚀 Complete Shopping Workflows

Workflow 1: Conversational Product Discovery

// Complete AI-assisted shopping flow
async function conversationalShopping() {
console.log('=== AI Shopping Assistant ===\n');

const conversationHistory = [];

// Step 1: Initial conversation (no auth)
const chat1Response = await fetch('https://api.brdz.link/api/marketplace/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: 'I need a birthday gift for my mom'
})
});

const chat1 = await chat1Response.json();

console.log('You: I need a birthday gift for my mom');
console.log(`AI: ${chat1.reply}\n`);

conversationHistory.push(
{ role: 'user', content: 'I need a birthday gift for my mom' },
{ role: 'assistant', content: chat1.reply }
);

// Step 2: Provide more context (no auth)
const chat2Response = await fetch('https://api.brdz.link/api/marketplace/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: 'She loves gardening and handmade pottery',
conversation_history: conversationHistory
})
});

const chat2 = await chat2Response.json();

console.log('You: She loves gardening and handmade pottery');
console.log(`AI: ${chat2.reply}\n`);

// Step 3: AI suggests search
if (chat2.intent === 'SEARCH') {
console.log('AI detected SEARCH intent - proceeding to product search\n');

// Step 4: Search products (no auth)
const searchResponse = await fetch('https://api.brdz.link/api/marketplace/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: 'handmade pottery planter',
sources: ['etsy', 'tokopedia'],
limit: 10
})
});

const searchResults = await searchResponse.json();

console.log(`Found ${searchResults.count} products:\n`);

searchResults.products.slice(0, 3).forEach((product, index) => {
console.log(`${index + 1}. ${product.title}`);
console.log(` Price: $${product.pricing.total}`);
console.log(` Shop: ${product.vendor.shop_name}`);
console.log(` Rating: ${product.metadata?.rating || 'N/A'}\n`);
});

return searchResults;
}

return conversationHistory;
}

// Usage
await conversationalShopping();

Workflow 2: Complete Purchase Flow with Web3 Payment

// End-to-end purchase workflow with blockchain payment
async function completePurchaseFlow(searchQuery, userWalletAddress, jwtToken, apiKey) {
console.log('=== Complete Purchase Flow ===\n');

try {
// Step 1: Search products (no auth)
console.log('Step 1: Searching products...');
const searchResponse = await fetch('https://api.brdz.link/api/marketplace/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: searchQuery,
sources: ['etsy'],
limit: 5
})
});

const searchResults = await searchResponse.json();

if (searchResults.products.length === 0) {
throw new Error('No products found');
}

console.log(`Found ${searchResults.count} products\n`);

// Step 2: Select product
const selectedProduct = searchResults.products[0];
console.log('Step 2: Product selected:');
console.log(` ${selectedProduct.title}`);
console.log(` Price: $${selectedProduct.pricing.total}\n`);

// Step 3: Create order (auth required)
console.log('Step 3: Creating order...');
const orderResponse = await fetch('https://api.brdz.link/api/marketplace/orders', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwtToken}`,
'x-api-key': apiKey
},
body: JSON.stringify({
product: selectedProduct,
recipient: {
name: 'Jane Smith',
phone: '+628123456789',
address: 'Jl. Sudirman No. 456, Jakarta Selatan 12190, Indonesia',
email: 'jane@example.com',
notes: 'Please call before delivery'
},
wallet_address: userWalletAddress,
chain_id: 'sepolia'
})
});

const order = await orderResponse.json();

console.log(`Order created: ${order.order.order_id}`);
console.log(`Amount to pay: ${order.payment_details.usdc_amount} USDC\n`);

// Step 4: Execute blockchain payment
console.log('Step 4: Processing payment...');

// Initialize Web3
const Web3 = require('web3');
const web3 = new Web3(window.ethereum);

const BRDZ_PAYMENT_ABI = [{
inputs: [
{ type: 'address', name: 'brdzWallet' },
{ type: 'uint256', name: 'amount' },
{ type: 'string', name: 'orderId' }
],
name: 'completePayment',
outputs: [],
stateMutability: 'nonpayable',
type: 'function'
}];

const contract = new web3.eth.Contract(
BRDZ_PAYMENT_ABI,
order.payment_details.contract_address
);

const amountInWei = web3.utils.toWei(
order.payment_details.usdc_amount.toString(),
'mwei' // USDC has 6 decimals
);

const tx = await contract.methods
.completePayment(
order.payment_details.wallet_address,
amountInWei,
order.order.order_id
)
.send({ from: userWalletAddress });

console.log(`Payment TX: ${tx.transactionHash}\n`);

// Step 5: Wait for blockchain relayer to update status
console.log('Step 5: Waiting for payment confirmation...');
await new Promise(resolve => setTimeout(resolve, 5000));

// Check order status
const statusResponse = await fetch(
`https://api.brdz.link/api/marketplace/orders/${order.order.order_id}`,
{
headers: {
'Authorization': `Bearer ${jwtToken}`,
'x-api-key': apiKey
}
}
);

const orderStatus = await statusResponse.json();

console.log(`Status: ${orderStatus.order.payment_status}`);

if (orderStatus.order.blockchain_tx_hash) {
console.log(`TX Hash: ${orderStatus.order.blockchain_tx_hash}`);
}

console.log('\n=== Purchase Complete ===');

return {
order_id: order.order.order_id,
product: selectedProduct.title,
amount: order.payment_details.usdc_amount,
status: orderStatus.order.payment_status,
tx_hash: tx.transactionHash
};

} catch (error) {
console.error(`Purchase failed: ${error.message}`);
throw error;
}
}

// Usage
await completePurchaseFlow(
'handmade ceramic planter',
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
'YOUR_JWT_TOKEN',
'YOUR_API_KEY'
);

Workflow 3: Multi-Marketplace Price Comparison

// Compare prices across marketplaces
async function priceComparison(searchQuery) {
console.log(`=== Price Comparison: "${searchQuery}" ===\n`);

// Search both marketplaces (no auth)
const response = await fetch('https://api.brdz.link/api/marketplace/search', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: searchQuery,
sources: ['etsy', 'tokopedia'],
limit: 20
})
});

const results = await response.json();

// Separate by marketplace
const etsyProducts = results.products.filter(p => p.source === 'etsy');
const tokopediaProducts = results.products.filter(p => p.source === 'tokopedia');

console.log(`Etsy: ${etsyProducts.length} products`);
console.log(`Tokopedia: ${tokopediaProducts.length} products\n`);

// Price analysis
const getPriceStats = (products) => {
const prices = products.map(p => p.pricing.total);
return {
min: Math.min(...prices),
max: Math.max(...prices),
avg: prices.reduce((a, b) => a + b, 0) / prices.length,
count: products.length
};
};

const etsyStats = getPriceStats(etsyProducts);
const tokopediaStats = getPriceStats(tokopediaProducts);

console.log('💰 Price Analysis:');
console.log('\nEtsy (USD):');
console.log(` Min: $${etsyStats.min.toFixed(2)}`);
console.log(` Max: $${etsyStats.max.toFixed(2)}`);
console.log(` Avg: $${etsyStats.avg.toFixed(2)}`);

console.log('\nTokopedia (converted to USD):');
console.log(` Min: $${tokopediaStats.min.toFixed(2)}`);
console.log(` Max: $${tokopediaStats.max.toFixed(2)}`);
console.log(` Avg: $${tokopediaStats.avg.toFixed(2)}`);

// Best deals
const allProducts = [...etsyProducts, ...tokopediaProducts]
.sort((a, b) => a.pricing.total - b.pricing.total);

console.log('\n🏆 Top 3 Best Deals:');
allProducts.slice(0, 3).forEach((product, index) => {
console.log(`${index + 1}. ${product.title}`);
console.log(` $${product.pricing.total} (${product.source})`);
console.log(` Shop: ${product.vendor.shop_name}`);
console.log(` Rating: ${product.metadata?.rating || 'N/A'}\n`);
});

return {
etsy: etsyStats,
tokopedia: tokopediaStats,
bestDeal: allProducts[0]
};
}

// Usage
await priceComparison('ceramic coffee mug');

🌍 Supported Marketplaces & Features

Marketplace Support

Etsy (International)

  • Currency: USD
  • Payment: Direct USDC (1:1 conversion)
  • Shipping: International
  • Features: Handmade, vintage, craft supplies
  • Scraping: Puppeteer with stealth plugins
  • Data: Title, price, images, shop info, ratings

Tokopedia (Indonesia)

  • Currency: IDR
  • Payment: Auto-converted to USDC via FX service
  • Shipping: Domestic Indonesia
  • Features: Wide range of products
  • Scraping: Puppeteer with stealth plugins
  • Data: Title, price (IDR), images, shop info, location, sales

Payment Features

  • Smart Contract: BRDZPayment.sol on Sepolia testnet
  • Contract Address: 0x7E93334bf4Cd3Bd15D2203D7E6d5A59A891C4a48
  • Payment Token: USDC (6 decimals)
  • Event Monitoring: Blockchain relayer auto-listens to PaymentCompleted events
  • Status Updates: Automatic order status update from PENDING to PAID

Order Processing Stages

  1. PENDING: Order created, awaiting payment
  2. PAID: Payment confirmed on blockchain
  3. COMPLETED: Product shipped and delivered (manual update for MVP)
  4. FAILED: Payment or order processing failed
  5. CANCELLED: Order cancelled by user or system

🔄 Complete Integration Flow Diagram

┌─────────────────────────────────────────────────────────────────┐
│ MARKETPLACE FLOW DIAGRAM │
└─────────────────────────────────────────────────────────────────┘

STEP 1: PRODUCT DISCOVERY (No Auth)
┌──────────────────────────┐
│ User opens marketplace │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Chat with AI assistant │
│ POST /marketplace/chat │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ AI detects SEARCH intent │
└──────────┬───────────────┘


STEP 2: PRODUCT SEARCH (No Auth)
┌──────────────────────────┐
│ Search products │
│ POST /marketplace/search │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ AI generates optimal │
│ search queries │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Scrape Etsy + Tokopedia │
│ (Puppeteer) │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Normalize products │
│ Unified schema │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ FX conversion for IDR │
│ (Tokopedia products) │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Return sorted results │
└──────────┬───────────────┘


STEP 3: ORDER CREATION (Auth Required)
┌──────────────────────────┐
│ User login/authenticate │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ User selects product │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Enter recipient info │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Create order │
│ POST /marketplace/orders │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Calculate USDC amount │
│ (with FX for IDR) │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Save to database │
│ Status: PENDING │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Return payment details │
│ (contract, amount, etc) │
└──────────┬───────────────┘


STEP 4: BLOCKCHAIN PAYMENT
┌──────────────────────────┐
│ User approves USDC spend │
│ (MetaMask/Web3) │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Execute completePayment()│
│ on BRDZPayment contract │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ PaymentCompleted event │
│ emitted │
└──────────┬───────────────┘


STEP 5: PAYMENT CONFIRMATION
┌──────────────────────────┐
│ Blockchain relayer │
│ listens to events │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Update order status │
│ PENDING → PAID │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Store blockchain TX hash │
└──────────┬───────────────┘


STEP 6: ORDER FULFILLMENT (MVP: Manual)
┌──────────────────────────┐
│ Admin notified │
│ (console log) │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Merchant contacted │
│ Product shipped │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ Update status │
│ PAID → COMPLETED │
└──────────┬───────────────┘

v
[✅ DONE]

═══════════════════════════════════════════════════════════════

USER ORDER TRACKING (Auth Required):
┌──────────────────────────┐
│ Check order status │
│ GET /orders/:order_id │
└──────────┬───────────────┘

v
┌──────────────────────────┐
│ View order history │
│ GET /orders │
└──────────────────────────┘

📊 Database Schema Reference

marketplace_orders Table

- order_id VARCHAR(100) PRIMARY KEY
- user_id INTEGER NOT NULL
- product_data JSONB NOT NULL
- vendor_data JSONB NOT NULL
- pricing_data JSONB NOT NULL
- recipient_data JSONB NOT NULL
- payment_status VARCHAR(20) DEFAULT 'PENDING'
- payment_token VARCHAR(20) DEFAULT 'USDC'
- token_amount DECIMAL(20, 6)
- fiat_amount DECIMAL(20, 2)
- fiat_currency VARCHAR(10)
- chain_id VARCHAR(50) DEFAULT 'sepolia'
- wallet_address VARCHAR(100)
- blockchain_tx_hash VARCHAR(100)
- contract_address VARCHAR(100) DEFAULT '0x7E93334bf4Cd3Bd15D2203D7E6d5A59A891C4a48'
- created_at TIMESTAMP DEFAULT NOW()
- paid_at TIMESTAMP
- completed_at TIMESTAMP
- search_query TEXT
- ai_conversation JSONB

⚠️ Important Notes & Warnings

MVP Limitations

This is an MVP implementation with manual fulfillment. Automated merchant notification and shipping integration are not yet implemented. Admin must manually:

  • Contact merchant after payment confirmation
  • Track shipping status
  • Update order status to COMPLETED
Product Availability

Product availability is scraped in real-time but may change between search and purchase. Always verify product is still in stock on the marketplace website before finalizing order.

Currency Conversion

IDR products from Tokopedia are automatically converted to USDC using the existing FX service. Exchange rates are fetched in real-time during order creation. Rate is saved with order for reference.

Blockchain Network

Current implementation uses Sepolia testnet for USDC payments. Production deployment will use mainnet with real USDC.

Order Monitoring

Blockchain relayer automatically monitors PaymentCompleted events and updates order status. No manual intervention needed for payment confirmation.

Public vs Protected Endpoints

Chat and Search endpoints are public (no auth required) to allow users to browse products before logging in. Order operations require authentication for security.


🚨 Troubleshooting Guide

Common Issues & Solutions

Issue 1: "Chat service unavailable"

Cause: Groq API error or rate limit
Solution: Check Groq API configuration and implement retry logic

Issue 2: "Search failed - scraper timeout"

Cause: Marketplace website blocking or slow response
Solution:

  • Check if marketplace website is accessible
  • Verify Puppeteer configuration
  • Use fewer sources or reduce limit

Issue 3: "Authentication required"

Cause: Missing or invalid JWT token for order endpoints
Solution: Ensure user is logged in and token is provided in headers

Issue 4: "Payment not confirmed"

Cause: Blockchain relayer not running or event not detected
Solution:

  • Check blockchain relayer is running (auto-starts in app.js)
  • Verify transaction on Etherscan
  • Check smart contract address matches

Issue 5: "Product price changed"

Cause: Price changed between search and order creation
Solution: Re-search product and inform user of price change


📚 API Reference Summary

Quick Reference Table

EndpointMethodAuthDescription
/marketplace/chatPOSTNoSend message to AI assistant
/marketplace/searchPOSTNoSearch products across marketplaces
/marketplace/ordersPOSTYesCreate new order
/marketplace/orders/:order_idGETYesGet order details
/marketplace/ordersGETYesGet user order history

Authentication Summary

Endpoint CategoryAuth RequiredHeaders Needed
Chat Operations❌ NoContent-Type only
Search Operations❌ NoContent-Type only
Order Operations✅ YesAuthorization + x-api-key + Content-Type

💬 Support & Feedback

For technical support, API issues, or feature requests related to Marketplace integration:

  • Review the documentation above
  • Check error codes and troubleshooting guide
  • Test with Sepolia testnet first
  • Contact Anantla technical support
  • Report bugs via support channels

🚀 Roadmap & Future Features

Planned Enhancements

  • Automated Fulfillment: Direct merchant API integration
  • More Marketplaces: Amazon, AliExpress, Shopee support
  • Advanced AI: Product recommendations, price predictions
  • Multi-Chain: Support for Polygon, BSC, other EVM chains
  • Fiat On-ramp: Buy USDC with credit card directly
  • Order Tracking: Real-time shipping status updates
  • Dispute Resolution: Built-in escrow and arbitration
  • Loyalty Rewards: Cashback in USDC for purchases