import { createPodiumClient, ApiError } from '@podium-sdk/node-sdk'
const client = createPodiumClient({
apiKey: process.env.PODIUM_API_KEY
})
Product Catalog Management
Create, Configure, and Publish a Product
const product = await client.merchantProducts.create({
creatorId: 'creator_abc',
requestBody: {
name: 'Organic Face Serum',
slug: 'organic-face-serum',
description: 'Lightweight hydrating serum with hyaluronic acid and vitamin C',
price: 2500,
maxDiscount: 500,
allowedPointSources: null,
media: [
{ url: 'https://cdn.example.com/serum-hero.jpg', type: 'IMAGE', order: 0 },
{ url: 'https://cdn.example.com/serum-texture.jpg', type: 'IMAGE', order: 1 },
],
},
})
await client.merchantProducts.updateByProductId({
creatorId: 'creator_abc',
productId: product.id,
requestBody: {
supply: 200,
pointEligibility: 'ELIGIBLE',
shippingType: 'STANDARD',
attributes: [
{
name: 'Size',
type: 'VARIANT',
variants: [
{ value: '30ml', price: 2500, supply: 100, order: 0 },
{ value: '50ml', price: 3500, supply: 60, order: 1 },
{ value: '100ml', price: 5000, supply: 40, order: 2 },
],
},
],
},
})
await client.merchantProducts.publish({
creatorId: 'creator_abc',
productId: product.id,
requestBody: { userId: 'admin_user_id' },
})
List and Filter Products
const published = await client.product.list({
categories: '1,2,3',
page: 1,
limit: 20,
})
const creatorProducts = await client.merchantProducts.list({
creatorId: 'creator_abc',
status: 'PUBLISHED',
})
Order and Checkout Workflows
Stripe Checkout (Consumer App)
const order = await client.userOrders.create({
id: userId,
requestBody: { productId: 'clx9prod001', quantity: 1 },
})
await client.userOrderProducts.createByProductId({
id: userId,
orderId: order.id,
productId: 'clx9prod001',
requestBody: { quantity: 1, variantIds: ['clx9var_30ml'] },
})
const shippingQuote = await client.order.createShippingQuote({
id: order.id,
requestBody: {
firstName: 'Jane',
lastName: 'Doe',
address: {
line1: '123 Main St',
line2: null,
city: 'San Francisco',
state: 'CA',
postalCode: '94102',
countryCode: 'US',
},
},
})
const checkout = await client.userOrder.checkout({
id: userId,
orderId: order.id,
requestBody: { points: 500 },
})
// checkout contains Stripe PaymentIntent clientSecret
// After Stripe webhook confirms payment:
await client.userOrderPoints.replaceFinalize({
id: userId,
orderId: order.id,
})
x402 Checkout (Agent)
The x402 payment flow uses HTTP directly — it negotiates USDC payment via response headers:const response = await fetch(
`https://api.podium.build/api/v1/x402/order/${orderId}/pay`,
{ method: 'POST' }
)
if (response.status === 402) {
const requirements = response.headers.get('X-PAYMENT-REQUIREMENTS')
const parsed = JSON.parse(atob(requirements!))
const paymentPayload = await signUsdcTransfer({
to: parsed.payTo,
amount: parsed.maxAmountRequired,
network: 'base',
})
const receipt = await fetch(
`https://api.podium.build/api/v1/x402/order/${orderId}/pay`,
{
method: 'POST',
headers: { 'X-PAYMENT': btoa(JSON.stringify(paymentPayload)) },
}
)
}
await client.x402.createOrderPay({ id: orderId })
Buy Now (Single-Step Purchase)
const result = await client.product.buyNow({
id: 'clx9prod001',
requestBody: {
quantity: 1,
variantIds: ['clx9var_30ml'],
shouldUseStripe: true,
},
})
Guest Checkout
const guestOrder = await client.guests.createOrder({
requestBody: { productId: 'clx9prod001', quantity: 1 },
})
await client.guests.createOrderProductByProductId({
id: guestOrder.id,
productId: 'clx9prod001',
requestBody: { quantity: 1 },
})
const checkout = await client.guests.checkout({ id: guestOrder.id })
Campaign Workflows
Create and Run a Swipe Campaign
const campaign = await client.campaigns.create({
requestBody: {
creatorId: 'creator_abc',
type: 'SWIPE',
},
})
await client.campaigns.replace({
id: campaign.id,
requestBody: {
title: 'What moisturizer matches your skin?',
description: 'Swipe right on your favorites',
startDate: new Date().toISOString(),
endDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
},
})
await client.campaigns.updateSubmit({ id: campaign.id })
await client.campaigns.publish({
id: campaign.id,
requestBody: { requiresReview: false },
})
await client.campaigns.vote({
id: campaign.id,
requestBody: {
userId: 'user_123',
votes: [{ attributeId: 1, optionId: 2 }],
},
})
const analytics = await client.campaigns.getAnalytics({ id: campaign.id })
Run a Survey Campaign
const survey = await client.campaigns.create({
requestBody: {
creatorId: 'creator_abc',
type: 'SURVEY',
},
})
await client.campaigns.createSurvey({
id: survey.id,
requestBody: {
userId: 'user_456',
responses: [
{ questionId: 1, answer: 'Oily skin' },
{ questionId: 2, answer: ['Hydration', 'SPF'] },
],
},
})
const report = await client.campaigns.getSurveyReport({ id: survey.id })
Companion Agent Workflows
Full Agent Lifecycle
const user = await client.user.create({
requestBody: {
email: 'shopper@example.com',
privyId: 'did:privy:abc123',
},
})
const { data: profile } = await client.companion.createProfile({
userId: user.id,
requestBody: {
skinType: 'Oily',
concerns: ['Acne', 'SPF protection'],
priceRange: { min: 15, max: 50 },
brands: ['CeraVe', 'The Ordinary'],
avoidances: ['fragrance', 'alcohol'],
},
})
const { data: recs } = await client.companion.listRecommendations({
userId: user.id,
})
await client.companion.createInteractions({
requestBody: {
userId: user.id,
productId: recs[0].id,
action: 'RANK_UP',
},
})
const { data: order } = await client.companion.createOrders({
requestBody: {
userId: user.id,
productId: recs[0].id,
shippingAddress: { street: '123 Main St', city: 'San Francisco', state: 'CA', zip: '94102' },
email: 'shopper@example.com',
},
})
await client.companion.createProfilePoints({
userId: user.id,
requestBody: {
amount: 25,
details: { reason: 'order_placed', orderId: order.id },
},
})
Points and Loyalty
Earn and Spend Points
await client.user.createPoints({
id: userId,
requestBody: {
amount: 50,
creatorId: 'creator_abc',
details: { source: 'campaign_completion', campaignId: 'campaign_abc' },
},
})
const balance = await client.user.getPoints({ id: userId })
const history = await client.user.getPointsHistory({
id: userId,
page: 1,
limit: 20,
order: 'desc',
})
// Apply points to an order, then finalize after payment
await client.userOrder.checkout({
id: userId,
orderId: orderId,
requestBody: { points: 200 },
})
// After payment succeeds:
await client.userOrderPoints.replaceFinalize({ id: userId, orderId })
// If payment fails, revert the points hold:
await client.userOrderPoints.revert({ id: userId, orderId })
Task Pool (On-Chain Bounties)
Create a Task
const { data: task } = await client.tasks.createTask({
requestBody: {
merchantAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18',
amountUSDC: 5.0,
acceptanceCriteria: 'Write a 200+ word product review with personal experience, star rating 1-5, and photo',
verificationMethod: 'Oracle',
durationSeconds: 86400,
campaignId: 'campaign_abc',
},
})
Solver Workflow (HTTP)
const BASE = 'https://api.podium.build/api/v1'
const headers = {
'Authorization': `Bearer ${process.env.PODIUM_API_KEY}`,
'Content-Type': 'application/json',
}
const solver = await fetch(`${BASE}/solver/register`, {
method: 'POST',
headers,
body: JSON.stringify({ walletAddress: '0xSolverAddress...' }),
}).then(r => r.json())
const tasks = await fetch(`${BASE}/solver/tasks`, { headers }).then(r => r.json())
await fetch(`${BASE}/solver/tasks/${taskId}/claim`, {
method: 'POST',
headers,
})
await fetch(`${BASE}/solver/tasks/${taskId}/submit`, {
method: 'POST',
headers,
body: JSON.stringify({
proof: 'https://example.com/review-link',
metadata: { wordCount: 342, rating: 4 },
}),
})
On-Chain Rewards
Create and Manage Reward Programs
const reward = await client.nftRewards.createNftReward({
requestBody: {
type: 'FREE_PRODUCT',
creatorId: 'creator_abc',
},
})
await client.nftRewards.replace({
id: reward.id,
requestBody: {
name: 'Free Serum Reward',
description: 'Redeem for a free Organic Face Serum',
imageUrl: 'https://cdn.example.com/reward.png',
points: 500,
},
})
await client.nftRewards.publish({ id: reward.id })
// Grant a reward to a user
await client.nftRewards.createNftRewardGrant({
id: reward.id,
requestBody: {
userId: 'user_123',
creatorId: 'creator_abc',
},
})
Check and Redeem User Rewards
const earned = await client.userNfTs.listEarned({ id: userId })
const redeemable = await client.userNfTs.listRedeemable({ id: userId })
await client.userNfTs.redeem({
id: userId,
network: 'base',
address: '0xNftContract...',
tokenId: '42',
})
const status = await client.userNfTs.getStatus({
id: userId,
network: 'base',
address: '0xNftContract...',
tokenId: '42',
})
Reward Types
| Type | Description |
|---|---|
FREE_PRODUCT | Redeem for a free product |
DISCOUNT_CODE | Percentage or fixed discount |
EVENT_PASS | Access pass for events |
POINTS | Bonus point grant |
EXCLUSIVE_ACCESS | Gated content or early access |
CUSTOM_REWARD | Custom reward type |
Agentic Commerce (Public Endpoints)
Query the Agentic Product Feed
No API key required — designed for machine consumption:const feed = await client.agentic.listProductsFeed({
page: 1,
limit: 20,
categories: '1,2,3',
})
const response = await fetch(
'https://api.podium.build/api/v1/agentic/products/feed?page=1&limit=20',
{
headers: {
'X-INTENT-CONTEXT': JSON.stringify({
concerns: ['hydration'],
priceRange: { min: 10, max: 50 },
}),
},
}
)
const products = await response.json()
Create an Agentic Checkout Session
const session = await client.agentic.createCheckoutSessions({
requestBody: {
items: [{ id: 'clx9prod001', quantity: 1 }],
shippingAddress: {
firstName: 'Jane',
lastName: 'Doe',
address: {
line1: '123 Main St',
line2: null,
city: 'San Francisco',
state: 'CA',
postalCode: '94102',
countryCode: 'US',
},
},
},
})
// Update the session with email
const updated = await client.agentic.updateCheckoutSessions({
id: session.id,
requestBody: { email: 'customer@example.com' },
})
// Check session state
const state = await client.agentic.getCheckoutSessions({ id: session.id })
Shopify Integration
List and Sync Shopify Products
const available = await client.shopify.getProductsAvailableByCreatorId({
creatorId: 'creator_abc',
})
await client.shopify.sync({
creatorId: 'creator_abc',
requestBody: { productIds: ['shopify_prod_1', 'shopify_prod_2'] },
})
const shop = await client.shopify.getShopByCreatorId({
creatorId: 'creator_abc',
})
Error Handling
All SDK methods throwApiError with structured error details:
import { createPodiumClient, ApiError } from '@podium-sdk/node-sdk'
const client = createPodiumClient({ apiKey: process.env.PODIUM_API_KEY })
try {
const products = await client.product.list({ page: 1 })
} catch (error) {
if (error instanceof ApiError) {
console.error(`${error.status} ${error.statusText}: ${error.message}`)
console.error('URL:', error.url)
console.error('Body:', error.body)
}
}
| Status | Meaning |
|---|---|
400 | Validation error (check request body) |
401 | Missing or invalid API key |
403 | Insufficient permissions for this resource |
404 | Resource not found |
409 | Conflict (e.g., duplicate slug) |
429 | Rate limit exceeded |

