Skip to main content

Installation

npm install @podium-sdk/node-sdk
The SDK is published as @podium-sdk/node-sdk on npm with full TypeScript type definitions.

Configuration

import { createPodiumClient } from '@podium-sdk/node-sdk'

const client = createPodiumClient({
  apiKey: process.env.PODIUM_API_KEY
})
The SDK auto-detects the environment from your key prefix:
Key PrefixRoutes To
podium_test_https://podium-staging.up.railway.app/api/v1
podium_live_https://api.podium.build/api/v1

Environment Setup

Add your API key to your .env file:
# Get your key from https://app.podium.build/onboarding
PODIUM_API_KEY=podium_test_sk_your_key_here
Never commit API keys to version control. Always load them from environment variables or a secrets manager.

Custom Base URL

Override the auto-detected base URL for local development or custom deployments:
const client = createPodiumClient({
  apiKey: process.env.PODIUM_API_KEY,
  baseUrl: 'http://localhost:3030/api/v1'
})

Multi-Tenant Context

Every API call is scoped to the organization that owns your API key. You don’t need to pass an organizationId — the Podium middleware extracts it from your key automatically. If your organization manages multiple creators, all creator-scoped operations (products, orders, campaigns) are accessible through your single API key:
const creatorA = await client.merchant.getBySlug({ slug: 'brand-a' })
const creatorB = await client.merchant.getBySlug({ slug: 'brand-b' })

SDK Namespaces

The SDK is organized into namespaces that mirror the API structure:
NamespaceCovers
client.productProduct listing, buy-now
client.merchantProductsProduct CRUD, variants, publish lifecycle, analytics
client.merchantCreator profiles, stats
client.merchantOrdersCreator order management, shipping labels
client.userUser creation, profile, points, orders, notifications
client.userOrderCheckout (Stripe, Coinbase, embedded wallet)
client.userOrdersOrder listing, creation
client.campaignsCampaign CRUD, voting, surveys, analytics
client.nftRewardsReward programs, minting, grants, publishing
client.userNfTsUser reward redemption, earned/redeemable queries
client.agenticAgentic product feed, checkout sessions
client.searchProduct search with filters
client.universalSearchCross-entity search with LLM-powered answers
client.x402x402 USDC payment processing
client.apiKeysAPI key rotation and management
client.organizationsOrganization settings

Basic Usage

const products = await client.product.list({ page: 1, limit: 20 })

const creator = await client.merchant.getBySlug({ slug: 'clean-beauty-co' })

const user = await client.user.create({
  requestBody: {
    email: 'user@example.com',
    privyId: 'did:privy:abc123'
  }
})

const balance = await client.user.getPoints({ id: user.id })

Pagination

List endpoints return paginated results. Use page and limit parameters:
const page1 = await client.product.list({ page: 1, limit: 20 })

const page2 = await client.product.list({ page: 2, limit: 20 })

Pagination Response Shape

All paginated responses include a pagination object:
interface PaginatedResponse<T> {
  data: T[];
  pagination: {
    page: number;
    limit: number;
    total: number;
  };
}

Iterate All Pages

async function getAllProducts() {
  const products = []
  let page = 1
  let hasMore = true

  while (hasMore) {
    const result = await client.product.list({ page, limit: 100 })
    products.push(...result.data)
    hasMore = result.data.length === 100
    page++
  }

  return products
}

Error Handling

The SDK throws typed errors with HTTP status codes and structured error bodies:
import { ApiError } from '@podium-sdk/node-sdk'

try {
  const products = await client.product.list({ page: 1 })
} catch (error) {
  if (error instanceof ApiError) {
    console.error(`API Error ${error.status}: ${error.message}`)
    console.error('Response body:', error.body)

    if (error.status === 401) console.log('Invalid API key')
    if (error.status === 429) console.log('Rate limited, retry later')
    if (error.status === 402) console.log('x402 payment required')
  }
}

Error Codes

StatusMeaning
400Bad request — invalid parameters
401Unauthorized — invalid or missing API key
402Payment required — x402 payment needed
403Forbidden — insufficient permissions
404Not found
409Conflict — duplicate resource
422Validation error — request body failed Zod validation
429Rate limited — check Retry-After header
500Server error

Validation Errors (422)

Podium uses Zod for request validation. Validation errors include field-level details:
{
  "status": 422,
  "error": "Validation Error",
  "details": [
    {
      "path": ["email"],
      "message": "Invalid email",
      "code": "invalid_string"
    },
    {
      "path": ["amount"],
      "message": "Expected number, received string",
      "code": "invalid_type"
    }
  ]
}

Retry and Backoff

The SDK does not include automatic retries. Implement retry logic for transient errors:
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3,
  baseDelayMs = 1000
): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error: any) {
      const isRetryable = [429, 500, 502, 503].includes(error.status);
      if (!isRetryable || attempt === maxRetries) throw error;

      const delay = baseDelayMs * Math.pow(2, attempt) + Math.random() * 500;
      await new Promise(r => setTimeout(r, delay));
    }
  }
  throw new Error('Unreachable');
}

const products = await withRetry(() =>
  client.product.list({ page: 1 })
)
For 429 responses, respect the Retry-After header when available.

Rate Limits

Rate limits are per-API-key and based on your subscription tier:
TierCalls/MonthBurst Rate
Builder (Free)10,00010 req/s
Growth ($99/mo)100,00050 req/s
Pro ($499/mo)1,000,000200 req/s
EnterpriseCustomCustom
Rate limit headers are included in every response:
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1709827260

SDK Generation

The SDK uses a hybrid generation approach:
  1. OpenAPI spec generated from Zod schemas via a build script
  2. Service classes auto-generated via openapi-typescript-codegen
  3. Wrapper layer maps generated services to clean namespaces
The SDK is regenerated from the Podium API’s OpenAPI spec whenever the API surface changes. Published versions on npm always reflect the latest API.

Versioning

The SDK follows semver. Breaking changes increment the major version:
npm install @podium-sdk/node-sdk@latest
Check the Podium API Playground for the latest endpoint documentation. The playground is always in sync with the production API.